home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / Drtf / reader.c < prev    next >
Text File  |  1996-07-05  |  88KB  |  3,535 lines

  1. /*
  2.  * - Need to document error code meanings.
  3.  * - Need to do something with \* on destinations.
  4.  * - Make the parameter a long?
  5.  *
  6.  * reader.c - RTF file reader.  Release 1.10.
  7.  *
  8.  * ASCII 10 (\n) and 13 (\r) are ignored and silently discarded.
  9.  * Nulls are also discarded.
  10.  * (although the read hook will still get a look at them.)
  11.  *
  12.  * "\:" is not a ":", it's a control symbol.  But some versions of
  13.  * Word seem to write "\:" for ":".  This reader treats "\:" as a
  14.  * plain text ":"
  15.  *
  16.  * 19 Mar 93
  17.  * - Add hack to skip "{\*\keycode ... }" group in stylesheet.
  18.  * This is probably the wrong thing to do, but it's simple.
  19.  * 13 Jul 93
  20.  * - Add THINK C awareness to malloc() declaration.  Necessary so
  21.  * compiler knows the malloc argument is 4 bytes.  Ugh.
  22.  * 07 Sep 93
  23.  * - Text characters are mapped onto standard codes, which are placed
  24.  * in rtfMinor.
  25.  * - Eliminated use of index() function.
  26.  * 05 Mar 94
  27.  * - Added zillions of new symbols (those defined in RTF spec 1.2).
  28.  * 14 Mar 94
  29.  * - Public functions RTFMsg() and RTFPanic() now take variable arguments.
  30.  * This means RTFPanic() now is used in place of what was formerly the
  31.  * internal function Error().
  32.  * - 8-bit characters are now legal, so they're not converted to \'xx
  33.  * hex char representation now.
  34.  * 01 Apr 94
  35.  * - Added public variables rtfLineNum and rtfLinePos.
  36.  * - #include string.h or strings.h, avoiding strncmp() problem where
  37.  * last argument is treated as zero when prototype isn't available.
  38.  * 04 Apr 94
  39.  * - Treat style numbers 222 and 0 properly as "no style" and "normal".
  40.  
  41.  * -- 24apr94 -- d.g.gilbert, gilbertd@bio.indiana.edu
  42.  * -- modifications for use w/ DCLAP & NCBI cross-platform toolkits
  43.  * -- all changes affecting function incased in #ifdef DCLAP
  44.   
  45.  */
  46.  
  47.  
  48. #define DCLAP
  49.  
  50. #ifdef DCLAP
  51. #include <ncbi.h>
  52. #define RTFBreakInData -6         /* mark end of data buffer, but not EOF */
  53. #define STDARG
  54. #endif
  55.  
  56.  
  57.  
  58. # ifndef STRING_H
  59. # define STRING_H <string.h>
  60. # endif
  61.  
  62. # include    <stdio.h>
  63. # include    <ctype.h>
  64. # include    STRING_H
  65. # ifdef STDARG
  66. # include    <stdarg.h>
  67. # else
  68. # ifdef    VARARGS
  69. # include    <varargs.h>
  70. # endif    /* VARARGS */
  71. # endif    /* STDARG */
  72.  
  73.  
  74. # define    rtfInternal
  75. # include    "rtf.h"
  76. # include "rtfmaps.h"    /* dgg */
  77. # undef        rtfInternal
  78.  
  79.  
  80. /* # include    "tokenscan.h" */
  81. /*----------- bundled this one in -----------------*/
  82. #define    tsNoConcatDelims    0x01    /* all delimiters are significant */
  83. typedef    struct TSScanner    TSScanner;
  84.  
  85. struct TSScanner
  86. {
  87.     void    (*scanInit) (char    *p);
  88.     char    *(*scanScan) ();
  89.     char    *scanDelim;
  90.     char    *scanQuote;
  91.     char    *scanEscape;
  92.     char    *scanEos;
  93.     short    scanFlags;
  94. };
  95.  
  96.  
  97. static void TSScanInit (char    *p);
  98. static void TSSetScanner (TSScanner    *p);
  99. static void TSGetScanner (TSScanner    *p);
  100. static void TSSetScanPos (char    *p);
  101.  
  102. static char    *TSScan (void);
  103. static char    *TSGetScanPos (void);
  104. static short TSIsScanDelim (char c);
  105. static short TSIsScanQuote (char c);
  106. static short TSIsScanEscape (char c);
  107. static short TSIsScanEos (char c);
  108. static short TSTestScanFlags (short flags);
  109.  
  110. /*----------------------------*/
  111.  
  112.  
  113.  
  114. /*
  115.  * Return pointer to new element of type t, or NULL
  116.  * if no memory available.
  117.  */
  118.  
  119. # define    New(t)    ((t *) RTFAlloc ((short) sizeof (t)))
  120.  
  121.  
  122. /* maximum number of character values representable in a byte */
  123.  
  124. # define    charSetSize        256
  125.  
  126. /* charset stack size */
  127.  
  128. # define    maxCSStack        10
  129.  
  130.  
  131. #ifndef DCLAP
  132. #ifndef THINK_C
  133. extern char    *malloc ();
  134. #else
  135. extern void    *malloc(size_t);
  136. #endif
  137. #endif
  138.  
  139. static void    _RTFGetToken ();
  140. static void    _RTFGetToken2 ();
  141. static short    GetChar ();
  142. static void    ReadFontTbl ();
  143. static void    ReadColorTbl ();
  144. static void    ReadStyleSheet ();
  145. static void    ReadInfoGroup ();
  146. static void    ReadPictGroup ();
  147. static void    ReadObjGroup ();
  148. static void    LookupInit ();
  149. static void Lookup (char    *s);
  150.  
  151. static short    Hash (char    * s);
  152.  
  153. static void    CharSetInit ();
  154. static void    ReadCharSetMaps ();
  155.  
  156.  
  157. /*
  158.  * Public variables (listed in rtf.h)
  159.  */
  160.  
  161. short    rtfClass;
  162. short    rtfMajor;
  163. short    rtfMinor;
  164. short    rtfParam;
  165. char    *rtfTextBuf = NULL;
  166. short    rtfTextLen;
  167.  
  168. long    rtfLineNum;
  169. short    rtfLinePos;
  170.  
  171.  
  172. /*
  173.  * Private stuff
  174.  */
  175.  
  176. static short    pushedChar;    /* pushback char if read too far */
  177.  
  178. static short    pushedClass;    /* pushed token info for RTFUngetToken() */
  179. static short    pushedMajor;
  180. static short    pushedMinor;
  181. static short    pushedParam;
  182. static char    *pushedTextBuf = NULL;
  183.  
  184. static short    prevChar;
  185. static short    bumpLine;
  186.  
  187.  
  188. static RTFFont    *fontList = NULL;    /* these lists MUST be */
  189. static RTFColor    *colorList =  NULL;    /* initialized to NULL */
  190. static RTFStyle    *styleList =  NULL;
  191.  
  192.  
  193. static FILE    *rtffp = stdin;
  194.  
  195. static char    *inputName =  NULL;
  196. static char    *outputName =  NULL;
  197.  
  198. /*
  199.  * This array is used to map standard character names onto their numeric codes.
  200.  * The position of the name within the array is the code.
  201.  * stdcharnames.h is generated in the ../h directory.
  202.  */
  203.  
  204. static char    *stdCharName[] = {
  205. # include    "stdcharnames.h"
  206.      NULL
  207. };
  208.  
  209.  
  210.  
  211.  
  212.  
  213. /*
  214.  * These arrays are used to map RTF input character values onto the standard
  215.  * character names represented by the values.  Input character values are
  216.  * used as indices into the arrays to produce standard character codes.
  217.  */
  218.  
  219.  
  220. static char    *genCharSetFile =  NULL;
  221. #if 0 
  222. static short    genCharCode[charSetSize];
  223. #else
  224. static short  * genCharCode = ansi_gen_CharCode;
  225. #endif
  226. static short    haveGenCharSet = 0;
  227.  
  228. static char    *symCharSetFile = (char *) NULL;
  229. #if 0 
  230. static short    symCharCode[charSetSize];    
  231. #else
  232. static short  *symCharCode = ansi_sym_CharCode;
  233. #endif
  234. static short    haveSymCharSet = 0;
  235.  
  236. static short    curCharSet = rtfCSGeneral;
  237. static short    * curCharCode = ansi_gen_CharCode;
  238.  
  239. /*
  240.  * By default, the reader is configured to handle charset mapping invisibly,
  241.  * including reading the charset files and switching charset maps as necessary
  242.  * for Symbol font.
  243.  */
  244.  
  245. static short    autoCharSetFlags;
  246.  
  247. /*
  248.  * Stack for keeping track of charset map on group begin/end.  This is
  249.  * necessary because group termination reverts the font to the previous
  250.  * value, which may implicitly change it.
  251.  */
  252.  
  253. static short    csStack[maxCSStack];
  254. static short    csTop = 0;
  255.  
  256.  
  257. /*
  258.  * Initialize the reader.  This may be called multiple times,
  259.  * to read multiple files.  The only thing not reset is the input
  260.  * stream; that must be done with RTFSetStream().
  261.  */
  262.  
  263. void
  264. RTFInit ()
  265. {
  266. short    i;
  267. RTFColor    *cp;
  268. RTFFont        *fp;
  269. RTFStyle    *sp;
  270. RTFStyleElt    *eltList, *ep;
  271.  
  272.  
  273.     if (rtfTextBuf == NULL)    /* initialize the text buffers */
  274.     {
  275.         rtfTextBuf = RTFAlloc (rtfBufSiz);
  276.         pushedTextBuf = RTFAlloc (rtfBufSiz);
  277.         if (rtfTextBuf ==  NULL
  278.             || pushedTextBuf ==  NULL)
  279.             RTFPanic ("Cannot allocate text buffers.");
  280.         rtfTextBuf[0] = pushedTextBuf[0] = '\0';
  281.     }
  282.  
  283.     RTFFree (inputName);
  284.     RTFFree (outputName);
  285.     inputName = outputName =  NULL;
  286.             
  287.     /* initialize lookup table */
  288.     LookupInit ();
  289.  
  290.     for (i = 0; i < rtfMaxClass; i++)
  291.         RTFSetClassCallback (i,  NULL);
  292.     for (i = 0; i < rtfMaxDestination; i++)
  293.         RTFSetDestinationCallback (i, NULL);
  294.  
  295.     /* install built-in destination readers */
  296.     RTFSetDestinationCallback (rtfFontTbl, ReadFontTbl);
  297.     RTFSetDestinationCallback (rtfColorTbl, ReadColorTbl);
  298.     RTFSetDestinationCallback (rtfStyleSheet, ReadStyleSheet);
  299.     RTFSetDestinationCallback (rtfInfo, ReadInfoGroup);
  300.     /* dgg -- want to process pict...  RTFSetDestinationCallback (rtfPict, ReadPictGroup); */
  301.     RTFSetDestinationCallback (rtfObject, ReadObjGroup);
  302.  
  303.  
  304.     RTFSetReadHook ( NULL);
  305.  
  306.     /* dump old lists if necessary */
  307.  
  308.     while (fontList !=  NULL)
  309.     {
  310.         fp = fontList->rtfNextFont;
  311.         RTFFree (fontList->rtfFName);
  312.         RTFFree ((char *) fontList);
  313.         fontList = fp;
  314.     }
  315.     while (colorList !=  NULL)
  316.     {
  317.         cp = colorList->rtfNextColor;
  318.         RTFFree ((char *) colorList);
  319.         colorList = cp;
  320.     }
  321.     while (styleList !=  NULL)
  322.     {
  323.         sp = styleList->rtfNextStyle;
  324.         eltList = styleList->rtfSSEList;
  325.         while (eltList !=  NULL)
  326.         {
  327.             ep = eltList->rtfNextSE;
  328.             RTFFree (eltList->rtfSEText);
  329.             RTFFree ((char *) eltList);
  330.             eltList = ep;
  331.         }
  332.         RTFFree (styleList->rtfSName);
  333.         RTFFree ((char *) styleList);
  334.         styleList = sp;
  335.     }
  336.  
  337.     rtfClass = -1;
  338.     pushedClass = -1;
  339.     pushedChar = EOF;
  340.  
  341.     rtfLineNum = 0;
  342.     rtfLinePos = 0;
  343.     prevChar = EOF;
  344.     bumpLine = 0;
  345.  
  346.     CharSetInit ();
  347.     csTop = 0;
  348. }
  349.  
  350.  
  351. /*
  352.  * Set the reader's input stream to the given stream.  Can
  353.  * be used to redirect to other than the default (stdin).
  354.  */
  355.  
  356. void RTFSetStream (FILE    *stream)
  357. {
  358.     rtffp = stream;
  359. }
  360.  
  361.  
  362. /*
  363.  * Set or get the input or output file name.  These are never guaranteed
  364.  * to be accurate, only insofar as the calling program makes them so.
  365.  */
  366.  
  367. void
  368. RTFSetInputName (char    * name)
  369. {
  370.     if ((inputName = RTFStrSave (name)) == NULL)
  371.         RTFPanic ("RTFSetInputName: out of memory");
  372. }
  373.  
  374.  
  375. char *
  376. RTFGetInputName ()
  377. {
  378.     return (inputName);
  379. }
  380.  
  381.  
  382. void
  383. RTFSetOutputName (char    *name)
  384. {
  385.     if ((outputName = RTFStrSave (name)) ==  NULL)
  386.         RTFPanic ("RTFSetOutputName: out of memory");
  387. }
  388.  
  389.  
  390. char *
  391. RTFGetOutputName ()
  392. {
  393.     return (outputName);
  394. }
  395.  
  396.  
  397.  
  398. /* ---------------------------------------------------------------------- */
  399.  
  400. /*
  401.  * Callback table manipulation routines
  402.  */
  403.  
  404.  
  405. /*
  406.  * Install or return a writer callback for a token class
  407.  */
  408.  
  409.  
  410. static RTFFuncPtr    ccb[rtfMaxClass];        /* class callbacks */
  411.  
  412.  
  413. void
  414. RTFSetClassCallback (short aclass, RTFFuncPtr callback)
  415. {
  416.     if (aclass >= 0 && aclass < rtfMaxClass)
  417.         ccb[aclass] = callback;
  418. }
  419.  
  420.  
  421. RTFFuncPtr
  422. RTFGetClassCallback (short aclass)
  423. {
  424.     if (aclass >= 0 && aclass < rtfMaxClass)
  425.         return (ccb[aclass]);
  426.     return ((RTFFuncPtr) NULL);
  427. }
  428.  
  429.  
  430. /*
  431.  * Install or return a writer callback for a destination type
  432.  */
  433.  
  434. static RTFFuncPtr    dcb[rtfMaxDestination];    /* destination callbacks */
  435.  
  436.  
  437. void
  438. RTFSetDestinationCallback (short dest, RTFFuncPtr callback)
  439. {
  440.     if (dest >= 0 && dest < rtfMaxDestination)
  441.         dcb[dest] = callback;
  442. }
  443.  
  444.  
  445. RTFFuncPtr
  446. RTFGetDestinationCallback (short dest)
  447. {
  448.     if (dest >= 0 && dest < rtfMaxDestination)
  449.         return (dcb[dest]);
  450.     return ( NULL);
  451. }
  452.  
  453.  
  454. /* ---------------------------------------------------------------------- */
  455.  
  456. /*
  457.  * Token reading routines
  458.  */
  459.  
  460.  
  461. /*
  462.  * Read the input stream, invoking the writer's callbacks
  463.  * where appropriate.
  464.  */
  465.  
  466. void
  467. RTFRead ()
  468. {
  469.     while (RTFGetToken () != rtfEOF)
  470.         RTFRouteToken ();
  471. }
  472.  
  473.  
  474. /*
  475.  * Route a token.  If it's a destination for which a reader is
  476.  * installed, process the destination internally, otherwise
  477.  * pass the token to the writer's class callback.
  478.  */
  479.  
  480. void
  481. RTFRouteToken ()
  482. {
  483. RTFFuncPtr    p;
  484.  
  485.     if (rtfClass < 0 || rtfClass >= rtfMaxClass)    /* watchdog */
  486.     {
  487.         rtfTextBuf[rtfTextLen] = '\0'; 
  488.         RTFPanic ("Unknown class %d: %s (reader malfunction)",
  489.                             rtfClass, rtfTextBuf);
  490.     }
  491.     if (RTFCheckCM (rtfControl, rtfDestination)) /* this could be define/inline call */
  492.     {
  493.         /* invoke destination-specific callback if there is one */
  494.         if ((p = RTFGetDestinationCallback (rtfMinor)) != NULL)
  495.         {
  496.             (*p) ();
  497.             return;
  498.         }
  499.     }
  500.     /* invoke class callback if there is one */
  501.     if ((p = RTFGetClassCallback (rtfClass)) != NULL)
  502.         (*p) ();
  503. }
  504.  
  505.  
  506. /*
  507.  * Skip to the end of the current group.  When this returns,
  508.  * writers that maintain a state stack may want to call their
  509.  * state unstacker; global vars will still be set to the group's
  510.  * closing brace.
  511.  */
  512.  
  513. void
  514. RTFSkipGroup ()
  515. {
  516. short    level = 1;
  517.  
  518.     while (RTFGetToken () != rtfEOF)
  519.     {
  520.         if (rtfClass == rtfGroup)
  521.         {
  522.             if (rtfMajor == rtfBeginGroup)
  523.                 ++level;
  524.             else if (rtfMajor == rtfEndGroup)
  525.             {
  526.                 if (--level < 1)
  527.                     break;    /* end of initial group */
  528.             }
  529.         }
  530.     }
  531. }
  532.  
  533.  
  534. /*
  535.  * Read one token.  Call the read hook if there is one.  The
  536.  * token class is the return value.  Returns rtfEOF when there
  537.  * are no more tokens.
  538.  */
  539.  
  540. short
  541. RTFGetToken ()
  542. {
  543. RTFFuncPtr    p;
  544.  
  545.     for (;;)
  546.     {
  547.         _RTFGetToken ();
  548.         if ((p = RTFGetReadHook ()) != (RTFFuncPtr) NULL)
  549.             (*p) ();    /* give read hook a look at token */
  550.  
  551.         /* Silently discard newlines, carriage returns, nulls.  */
  552.         if (!(rtfClass == rtfText
  553.             && (rtfMajor == '\n' || rtfMajor == '\r'
  554.                         || rtfMajor == '\0')))
  555.             break;
  556.     }
  557.     return (rtfClass);
  558. }
  559.  
  560.  
  561. /*
  562.  * Install or return a token reader hook.
  563.  */
  564.  
  565. static RTFFuncPtr    readHook;
  566.  
  567.  
  568. void
  569. RTFSetReadHook (RTFFuncPtr f)
  570. {
  571.     readHook = f;
  572. }
  573.  
  574.  
  575. RTFFuncPtr
  576. RTFGetReadHook ()
  577. {
  578.     return (readHook);
  579. }
  580.  
  581.  
  582. void
  583. RTFUngetToken ()
  584. {
  585.     if (pushedClass >= 0)    /* there's already an ungotten token */
  586.         RTFPanic ("cannot unget two tokens");
  587.     if (rtfClass < 0)
  588.         RTFPanic ("no token to unget");
  589.     pushedClass = rtfClass;
  590.     pushedMajor = rtfMajor;
  591.     pushedMinor = rtfMinor;
  592.     pushedParam = rtfParam;
  593.     rtfTextBuf[rtfTextLen] = '\0'; 
  594.     (void) strcpy (pushedTextBuf, rtfTextBuf);
  595. }
  596.  
  597.  
  598. short
  599. RTFPeekToken ()
  600. {
  601.     _RTFGetToken ();
  602.     RTFUngetToken ();
  603.     return (rtfClass);
  604. }
  605.  
  606.  
  607. static void
  608. _RTFGetToken ()
  609. {
  610. RTFFont    *fp;
  611.  
  612.     /* first check for pushed token from RTFUngetToken() */
  613.  
  614.     if (pushedClass >= 0)
  615.     {
  616.         rtfClass = pushedClass;
  617.         rtfMajor = pushedMajor;
  618.         rtfMinor = pushedMinor;
  619.         rtfParam = pushedParam;
  620.         (void) strcpy (rtfTextBuf, pushedTextBuf);
  621.         rtfTextLen = strlen (rtfTextBuf);
  622.         pushedClass = -1;
  623.         return;
  624.     }
  625.  
  626.     /*
  627.      * Beyond this point, no token is ever seen twice, which is
  628.      * important, e.g., for making sure no "}" pops the font stack twice.
  629.      */
  630.  
  631.     _RTFGetToken2 ();
  632.     if (rtfClass == rtfText)    /* map RTF char to standard code */
  633.         rtfMinor = RTFMapChar (rtfMajor);
  634.  
  635.     /*
  636.      * If auto-charset stuff is activated, see if anything needs doing,
  637.      * like reading the charset maps or switching between them.
  638.      */
  639.  
  640.     if (autoCharSetFlags == 0)
  641.         return;
  642.  
  643.     if ((autoCharSetFlags & rtfReadCharSet)
  644.         && RTFCheckCM (rtfControl, rtfCharSet))
  645.     {
  646.         ReadCharSetMaps ();
  647.     }
  648.     else if ((autoCharSetFlags & rtfSwitchCharSet)
  649.         && RTFCheckCMM (rtfControl, rtfCharAttr, rtfFontNum))
  650.     {
  651.         if ((fp = RTFGetFont (rtfParam)) != NULL)
  652.         {
  653.             if (strncmp (fp->rtfFName, "Symbol", 6) == 0)
  654.                 curCharSet = rtfCSSymbol;
  655.             else
  656.                 curCharSet = rtfCSGeneral;
  657.             RTFSetCharSet (curCharSet);
  658.         }
  659.     }
  660.     else if ((autoCharSetFlags & rtfSwitchCharSet) && rtfClass == rtfGroup)
  661.     {
  662.         switch (rtfMajor)
  663.         {
  664.         case rtfBeginGroup:
  665.             if (csTop >= maxCSStack)
  666.                 RTFPanic ("_RTFGetToken: stack overflow");
  667.             csStack[csTop++] = curCharSet;
  668.             break;
  669.         case rtfEndGroup:
  670.             if (csTop <= 0)
  671.                 RTFPanic ("_RTFGetToken: stack underflow");
  672.             curCharSet = csStack[--csTop];
  673.             RTFSetCharSet (curCharSet);
  674.             break;
  675.         }
  676.     }
  677. }
  678.  
  679.  
  680. /* this shouldn't be called anywhere but from _RTFGetToken() */
  681.  
  682. static void
  683. _RTFGetToken2 ()
  684. {
  685. short    sign;
  686. short    c;
  687.  
  688.     /* initialize token vars */
  689.  
  690.     rtfClass = rtfUnknown;
  691.     rtfParam = rtfNoParam;
  692.     rtfTextLen = 0;
  693.   /* rtfTextBuf[0] = '\0'; */
  694.  
  695.     /* get first character, which may be a pushback from previous token */
  696.  
  697.     if (pushedChar != EOF)
  698.     {
  699.         c = pushedChar;
  700.         rtfTextBuf[rtfTextLen++] = c;
  701.         /* rtfTextBuf[rtfTextLen] = '\0';    //x */
  702.         pushedChar = EOF;
  703.     }
  704.     else if ((c = GetChar ()) == EOF)
  705.     {
  706.         rtfClass = rtfEOF;
  707.         return;
  708.     }
  709.     
  710. #ifdef DCLAP
  711.     if (c == RTFBreakInData)
  712.     {
  713.         rtfClass = rtfEOF;
  714.         rtfParam = RTFBreakInData;
  715.         return;
  716.     }
  717. #endif
  718.  
  719.     if (c == '{')
  720.     {
  721.         rtfClass = rtfGroup;
  722.         rtfMajor = rtfBeginGroup;
  723.         return;
  724.     }
  725.     if (c == '}')
  726.     {
  727.         rtfClass = rtfGroup;
  728.         rtfMajor = rtfEndGroup;
  729.         return;
  730.     }
  731.     if (c != '\\')
  732.     {
  733.         /*
  734.          * Two possibilities here:
  735.          * 1) ASCII 9, effectively like \tab control symbol
  736.          * 2) literal text char
  737.          */
  738.         if (c == '\t')            /* ASCII 9 */
  739.         {
  740.             rtfClass = rtfControl;
  741.             rtfMajor = rtfSpecialChar;
  742.             rtfMinor = rtfTab;
  743.         }
  744.         else
  745.         {
  746.             rtfClass = rtfText;
  747.             rtfMajor = c;
  748.         }
  749.         return;
  750.     }
  751.  
  752.     if ((c = GetChar ()) == EOF)
  753.     {
  754.         /* early eof, whoops (class is rtfUnknown) */
  755.         return;
  756.     }
  757.     if (!isalpha (c))
  758.     {
  759.         /*
  760.          * Three possibilities here:
  761.          * 1) hex encoded text char, e.g., \'d5, \'d3
  762.          * 2) special escaped text char, e.g., \{, \}
  763.          * 3) control symbol, e.g., \_, \-, \|, \<10>
  764.          */
  765.         if (c == '\'')                /* hex char */
  766.         {
  767.         short    c2;
  768.  
  769.             if ((c = GetChar ()) != EOF && (c2 = GetChar ()) != EOF)
  770.             {
  771.                 /* should do isxdigit check! */
  772.                 rtfClass = rtfText;
  773.                 rtfMajor = RTFCharToHex (c) * 16
  774.                         + RTFCharToHex (c2);
  775.                 return;
  776.             }
  777.             /* early eof, whoops (class is rtfUnknown) */
  778.             return;
  779.         }
  780.  
  781.         /* escaped char */
  782.         /*if (index (":{}\\", c) !=  NULL) /* escaped char */
  783.         if (c == ':' || c == '{' || c == '}' || c == '\\')
  784.         {
  785.             rtfClass = rtfText;
  786.             rtfMajor = c;
  787.             return;
  788.         }
  789.  
  790.         /* control symbol */
  791.         rtfTextBuf[rtfTextLen] = '\0';  
  792.         Lookup (rtfTextBuf);    /* sets class, major, minor */
  793.         return;
  794.     }
  795.     /* control word */
  796.     while (isalpha (c))
  797.     {
  798.         if ((c = GetChar ()) == EOF)
  799.             break;
  800.     }
  801.  
  802.     /*
  803.      * At this point, the control word is all collected, so the
  804.      * major/minor numbers are determined before the parameter
  805.      * (if any) is scanned.  There will be one too many characters
  806.      * in the buffer, though, so fix up before and restore after
  807.      * looking up.
  808.      */
  809.  
  810.     if (c != EOF)
  811.         rtfTextBuf[rtfTextLen-1] = '\0';
  812.     else
  813.         rtfTextBuf[rtfTextLen] = '\0';  
  814.     Lookup (rtfTextBuf);    /* sets class, major, minor */
  815.     if (c != EOF)
  816.         rtfTextBuf[rtfTextLen-1] = c;
  817.  
  818.     /*
  819.      * Should be looking at first digit of parameter if there
  820.      * is one, unless it's negative.  In that case, next char
  821.      * is '-', so need to gobble next char, and remember sign.
  822.      */
  823.  
  824.     sign = 1;
  825.     if (c == '-')
  826.     {
  827.         sign = -1;
  828.         c = GetChar ();
  829.     }
  830.     if (c != EOF && isdigit (c))
  831.     {
  832.         rtfParam = 0;
  833.         while (isdigit (c))    /* gobble parameter */
  834.         {
  835.             rtfParam = rtfParam * 10 + c - '0';
  836.             if ((c = GetChar ()) == EOF)
  837.                 break;
  838.         }
  839.         rtfParam *= sign;
  840.     }
  841.     /*
  842.      * If control symbol delimiter was a blank, gobble it.
  843.      * Otherwise the character is first char of next token, so
  844.      * push it back for next call.  In either case, delete the
  845.      * delimiter from the token buffer.
  846.      */
  847.     if (c != EOF)
  848.     {
  849.         if (c != ' ') pushedChar = c;
  850.         rtfTextBuf[--rtfTextLen] = '\0';
  851.     }
  852. }
  853.  
  854.  
  855. /*
  856.  * Read the next character from the input.  This handles setting the
  857.  * current line and position-within-line variables.  Those variable are
  858.  * set correctly whether lines end with CR, LF, or CRLF (the last being
  859.  * the tricky case).
  860.  *
  861.  * bumpLine indicates whether the line number should be incremented on
  862.  * the *next* input character.
  863.  */
  864.  
  865. static short
  866. GetChar ()
  867. {
  868. short    c;
  869. short    oldBumpLine;
  870.  
  871. #ifdef DCLAP
  872.     /* if (gReaderIsDead) c= EOF; else */
  873.   c= rtfGetOneChar() & 0xFFFF; /* !! DAMN INTs, short to short conversion screws this up ! */
  874.     if (c != EOF)
  875. #else
  876.     if ((c = getc (rtffp)) != EOF)
  877. #endif
  878.     {
  879.         rtfTextBuf[rtfTextLen++] = c;
  880.       /* rtfTextBuf[rtfTextLen] = '\0';  //x drop this for speed !? */
  881.     }
  882.  
  883. #if 0   
  884.         /* original code looks slow here...*/
  885.     if (prevChar == EOF) bumpLine = 1;
  886.     oldBumpLine = bumpLine;    /* non-zero if prev char was line ending */
  887.     bumpLine = 0;
  888.     if (c == '\r') bumpLine = 1;
  889.     else if (c == '\n') {
  890.         bumpLine = 1;
  891.         if (prevChar == '\r')        /* oops, previous \r wasn't */
  892.             oldBumpLine = 0;    /* really a line ending */
  893.         }
  894.     ++rtfLinePos;
  895.     if (oldBumpLine)    /* were we supposed to increment the */
  896.     {            /* line count on this char? */
  897.         ++rtfLineNum;
  898.         rtfLinePos = 1;
  899.     }
  900. #else
  901.     rtfLinePos++;
  902.     if (bumpLine || prevChar == EOF) {  /* prevchar == EOF only on 1st call !? */
  903.         if (! (c == '\n' && prevChar == '\r') ) {
  904.             ++rtfLineNum;
  905.             rtfLinePos = 1;
  906.             }
  907.         bumpLine= 0;
  908.         }
  909.     if (c == '\r' || c == '\n') bumpLine= 1;
  910. #endif
  911.  
  912.     prevChar = c;
  913.     return (c);
  914. }
  915.  
  916.  
  917. /*
  918.  * Synthesize a token by setting the global variables to the
  919.  * values supplied.  Typically this is followed with a call
  920.  * to RTFRouteToken().
  921.  *
  922.  * If a param value other than rtfNoParam is passed, it becomes
  923.  * part of the token text.
  924.  */
  925.  
  926. void RTFSetToken (short aclass,short major,short minor,short param,char* text)
  927. {
  928.     rtfClass = aclass;
  929.     rtfMajor = major;
  930.     rtfMinor = minor;
  931.     rtfParam = param;
  932.     rtfTextBuf[rtfTextLen] = '\0'; 
  933.     if (param == rtfNoParam)
  934.         (void) strcpy (rtfTextBuf, text);
  935.     else
  936.         sprintf (rtfTextBuf, "%s%d", text, param);
  937.     rtfTextLen = rtfTextLen; /* strlen (rtfTextBuf); */
  938. }
  939.  
  940.  
  941. /* ---------------------------------------------------------------------- */
  942.  
  943. /*
  944.  * Routines to handle mapping of RTF character sets
  945.  * onto standard characters.
  946.  *
  947.  * RTFStdCharCode(name)    given char name, produce numeric code
  948.  * RTFStdCharName(code)    given char code, return name
  949.  * RTFMapChar(c)    map input (RTF) char code to std code
  950.  * RTFSetCharSet(id)    select given charset map
  951.  * RTFGetCharSet()    get current charset map
  952.  *
  953.  * See ../h/README for more information about charset names and codes.
  954.  */
  955.  
  956.  
  957. /*
  958.  * Initialize charset stuff.
  959.  */
  960.  
  961. static void
  962. CharSetInit ()
  963. {
  964.     autoCharSetFlags = (rtfReadCharSet | rtfSwitchCharSet);
  965.     RTFFree (genCharSetFile);
  966.     genCharSetFile = NULL;
  967.     haveGenCharSet = 0;
  968.     RTFFree (symCharSetFile);
  969.     symCharSetFile =  NULL;
  970.     haveSymCharSet = 0;
  971.     curCharSet = rtfCSGeneral;
  972.     curCharCode = genCharCode;
  973.     RTFSetCharSet(curCharSet); /* dgg added */
  974. }
  975.  
  976.  
  977. /*
  978.  * Specify the name of a file to be read when auto-charset-file reading is
  979.  * done.
  980.  */
  981.  
  982. void
  983. RTFSetCharSetMap (char    * name,short csId)
  984. {
  985.     if ((name = RTFStrSave (name)) ==  NULL)    /* make copy */
  986.         RTFPanic ("RTFSetCharSetMap: out of memory");
  987.     switch (csId)
  988.     {
  989.     case rtfCSGeneral:
  990.         RTFFree (genCharSetFile);    /* free any previous value */
  991.         genCharSetFile = name;
  992.         break;
  993.     case rtfCSSymbol:
  994.         RTFFree (symCharSetFile);    /* free any previous value */
  995.         symCharSetFile = name;
  996.         break;
  997.     }
  998. }
  999.  
  1000.  
  1001. /*
  1002.  * Do auto-charset-file reading.
  1003.  */
  1004.  
  1005. static void
  1006. ReadCharSetMaps ()
  1007. {
  1008. char    buf[rtfBufSiz];
  1009.  
  1010.     rtfTextBuf[rtfTextLen] = '\0'; 
  1011.     if (genCharSetFile != NULL)
  1012.         strcpy (buf, genCharSetFile);
  1013.     else
  1014.         sprintf (buf, "%s-gen", &rtfTextBuf[1]);
  1015.     if (RTFReadCharSetMap (buf, rtfCSGeneral) == 0)
  1016.         RTFPanic ("ReadCharSetMaps: Cannot read charset map %s", buf);
  1017.     if (symCharSetFile !=  NULL)
  1018.         strcpy (buf, symCharSetFile);
  1019.     else
  1020.         sprintf (buf, "%s-sym", &rtfTextBuf[1]);
  1021.     if (RTFReadCharSetMap (buf, rtfCSSymbol) == 0)
  1022.         RTFPanic ("ReadCharSetMaps: Cannot read charset map %s", buf);
  1023. }
  1024.  
  1025.  
  1026.  
  1027. /*
  1028.  * Read in a file describing an RTF character set map.  Lines consist of pairs
  1029.  * associating character names with character values.
  1030.  *
  1031.  * If the filename is an absolute pathname, look in the specified location
  1032.  * only.  Otherwise try to find the file in the current directory or library.
  1033.  */
  1034.  
  1035. short
  1036. RTFReadCharSetMap (char    * file, short csId)
  1037. {
  1038.  
  1039. #if 1
  1040.     enum flags { kunknown, kmac, kansi, kpc, kpca };
  1041.     short    flag = kunknown;
  1042.  
  1043.     if (strncmp(file,"mac-",4) == 0) flag= kmac;
  1044.   else if (strncmp(file,"ansi-",5) == 0) flag= kansi; 
  1045.   else if (strncmp(file,"pca-",4) == 0) flag= kpca;
  1046.   else if (strncmp(file,"pc-",3) == 0) flag= kpc;
  1047.  
  1048.     switch (csId)
  1049.     {
  1050.     default:
  1051.         return (0);    /* illegal charset id */
  1052.  
  1053.     case rtfCSGeneral: {
  1054.         switch (flag) {
  1055.             case kmac    : genCharCode= mac_gen_CharCode; break;
  1056.             case kpca    : genCharCode= pca_gen_CharCode; break;
  1057.             case kpc    : genCharCode= pc_gen_CharCode; break;
  1058.             default:
  1059.             case kansi: genCharCode= ansi_gen_CharCode; break;
  1060.             }
  1061.         }
  1062.         break;
  1063.  
  1064.     case rtfCSSymbol: {
  1065.         switch (flag) {
  1066.             case kmac    : symCharCode= mac_sym_CharCode; break;
  1067.             case kpca    : symCharCode= pca_sym_CharCode; break;
  1068.             case kpc    : symCharCode= pc_sym_CharCode; break;
  1069.             default:
  1070.             case kansi: symCharCode= ansi_sym_CharCode; break;
  1071.             }
  1072.     }
  1073.         break;
  1074.     }
  1075.  
  1076. #else
  1077.     /* obsolete.... */
  1078. FILE    *f;
  1079. char    buf[rtfBufSiz];
  1080. char    *name;
  1081. unsigned char *p;
  1082. short    *stdCodeArray;
  1083. short    stdCode;
  1084. short    radix;
  1085. short    value;
  1086. short    i;
  1087. TSScanner    scanner;
  1088. char        *scanEscape;
  1089. char    *fn = "RTFReadCharSetMap";
  1090.  
  1091.  
  1092.     switch (csId)
  1093.     {
  1094.     default:
  1095.         return (0);    /* illegal charset id */
  1096.     case rtfCSGeneral:
  1097.         stdCodeArray = genCharCode;
  1098.         break;
  1099.     case rtfCSSymbol:
  1100.         stdCodeArray = symCharCode;
  1101.         break;
  1102.     }
  1103.  
  1104.     if ((f = RTFOpenLibFile (file, "r")) == NULL)
  1105.         return (0);
  1106.  
  1107.     /* clobber current mapping */
  1108.  
  1109.     for (i = 0; i < charSetSize; i++)
  1110.     {
  1111.         stdCodeArray[i] = rtfSC_nothing;
  1112.     }
  1113.  
  1114.     /*
  1115.      * Turn off scanner's backslash escape mechanism while reading
  1116.      * charset file.  Restore it later.
  1117.      */
  1118.     TSGetScanner (&scanner);
  1119.     scanEscape = scanner.scanEscape;
  1120.     scanner.scanEscape = "";
  1121.     TSSetScanner (&scanner);
  1122.  
  1123.     /* read file */
  1124.  
  1125.     while (fgets (buf, (short) sizeof (buf), f) !=  NULL)
  1126.     {
  1127.         if(buf[0] == '#')    /* skip comment lines */
  1128.             continue;
  1129.         TSScanInit (buf);
  1130.         if ((name = TSScan ()) == NULL)
  1131.             continue;    /* skip blank lines */
  1132.         if ((stdCode = RTFStdCharCode (name)) < 0)
  1133.         {
  1134.             RTFPanic ("%s: unknown character name: %s", fn, name);
  1135.             continue;
  1136.         }
  1137.         if ((p = (unsigned char*)TSScan ()) == NULL)
  1138.         {
  1139.             RTFPanic ("%s: malformed charset map line for character %s",
  1140.                                 fn, name);
  1141.             continue;
  1142.         }
  1143.         if (p[1] == '\0')    /* single char - use ascii value */
  1144.             value = (unsigned char) p[0];
  1145.         else
  1146.         {
  1147.             radix = 10;
  1148.             if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
  1149.             {
  1150.                 radix = 16;
  1151.                 p += 2;
  1152.             }
  1153.             value = 0;
  1154.             while (*p != '\0')
  1155.                 value = value * radix + RTFCharToHex(*p++);
  1156.         }
  1157.         if (value >= charSetSize)
  1158.         {
  1159.             RTFMsg ("%s: character value %d for %s too high\n",
  1160.                             fn, value, name);
  1161.             RTFPanic ("maximum value is %d", charSetSize - 1);
  1162.         }
  1163.         stdCodeArray[value] = stdCode;
  1164.     }
  1165.     scanner.scanEscape = scanEscape;
  1166.     TSSetScanner (&scanner);
  1167.     fclose(f);
  1168.  
  1169. #if 0
  1170.     strncpy( buf, file, rtfBufSiz);
  1171.     strncat( buf, ".h", rtfBufSiz);
  1172.     if ( (f = RTFOpenLibFile (buf, "w")) != NULL) {
  1173.         /* dgg -- write array to disk for later use */
  1174.         fprintf(f, "/* %s -- mapping charset to std. codes */\n\n", buf);
  1175.         fprintf(f, "static short %sCharCode[%d] = {\n", file, charSetSize);
  1176.         for (i = 0; i < charSetSize; i++) {
  1177.             char cend = '\n';
  1178.             /* if (i % 20 == 19) cend= '\n'; else cend= ' '; */
  1179.             fprintf(f, "%#3x,%c", stdCodeArray[i], cend);
  1180.             }
  1181.         fprintf(f, " };\n");
  1182.         fclose(f);
  1183.         }
  1184. #endif
  1185.  
  1186. #endif /* obsolete */
  1187.  
  1188.  
  1189.     switch (csId)
  1190.     {
  1191.     case rtfCSGeneral:
  1192.         haveGenCharSet = 1;
  1193.         break;
  1194.     case rtfCSSymbol:
  1195.         haveSymCharSet = 1;
  1196.         break;
  1197.     }
  1198.  
  1199.     return (1);
  1200. }
  1201.  
  1202.  
  1203. /*
  1204.  * Given a standard character name (a string), find its code (a number).
  1205.  * Return -1 if name is unknown.
  1206.  */
  1207.  
  1208. #if 0
  1209.     /* moved to rtfmap.h ... */
  1210. short
  1211. RTFStdCharCode (char    *name)
  1212. {
  1213. short    i;
  1214.  
  1215.     for (i = 0; i < rtfSC_MaxChar; i++)
  1216.     {
  1217.         if (strcmp (name, stdCharName[i]) == 0)
  1218.             return (i);
  1219.     }
  1220.     return (-1);
  1221. }
  1222.  
  1223.  
  1224. /*
  1225.  * Given a standard character code (a number), find its name (a string).
  1226.  * Return NULL if code is unknown.
  1227.  */
  1228.  
  1229. char * RTFStdCharName (short code)
  1230. {
  1231.     if (code < 0 || code >= rtfSC_MaxChar)
  1232.         return (  NULL);
  1233.     return (stdCharName[code]);
  1234. }
  1235.  
  1236. #endif
  1237.  
  1238.  
  1239. /*
  1240.  * Given an RTF input character code, find standard character code.
  1241.  * The translator should read the appropriate charset maps when it finds a
  1242.  * charset control.  However, the file might not contain one.  In this
  1243.  * case, no map will be available.  When the first attempt is made to
  1244.  * map a character under these circumstances, RTFMapChar() assumes ANSI
  1245.  * and reads the map as necessary.
  1246.  */
  1247.  
  1248. short
  1249. RTFMapChar (short c)
  1250. {
  1251. #if 0 /* //x DGG_DROP_FOR_SPEED */
  1252. /* don't need for each char !? */
  1253.     switch (curCharSet)
  1254.     {
  1255.     case rtfCSGeneral:
  1256.         if (!haveGenCharSet)
  1257.         {
  1258.             if (RTFReadCharSetMap ("ansi-gen", rtfCSGeneral) == 0)
  1259.                 RTFPanic ("RTFMapChar: cannot read ansi-gen");
  1260.         }
  1261.         break;
  1262.     case rtfCSSymbol:
  1263.         if (!haveSymCharSet)
  1264.         {
  1265.             if (RTFReadCharSetMap ("ansi-sym", rtfCSSymbol) == 0)
  1266.                 RTFPanic ("RTFMapChar: cannot read ansi-sym");
  1267.         }
  1268.         break;
  1269.     }
  1270. #endif
  1271.     if (c < 0 || c >= charSetSize)
  1272.         return (rtfSC_nothing);
  1273.     return (curCharCode[c]);
  1274. }
  1275.  
  1276.  
  1277. /*
  1278.  * Set the current character set.  If csId is illegal, uses general charset.
  1279.  */
  1280.  
  1281. void
  1282. RTFSetCharSet (short csId)
  1283. {
  1284.     switch (csId)
  1285.     {
  1286.     default:        /* use general if csId unknown */
  1287.     case rtfCSGeneral:
  1288.         curCharCode = genCharCode;
  1289.         curCharSet = csId;
  1290.         break;
  1291.     case rtfCSSymbol:
  1292.         curCharCode = symCharCode;
  1293.         curCharSet = csId;
  1294.         break;
  1295.     }
  1296.  
  1297. #if 1 /* //x */
  1298. /* moved here from MapChar */
  1299.     switch (curCharSet)
  1300.     {
  1301.     case rtfCSGeneral:
  1302.         if (!haveGenCharSet)
  1303.         {
  1304.             if (RTFReadCharSetMap ("ansi-gen", rtfCSGeneral) == 0)
  1305.                 RTFPanic ("RTFMapChar: cannot read ansi-gen");
  1306.         }
  1307.         break;
  1308.     case rtfCSSymbol:
  1309.         if (!haveSymCharSet)
  1310.         {
  1311.             if (RTFReadCharSetMap ("ansi-sym", rtfCSSymbol) == 0)
  1312.                 RTFPanic ("RTFMapChar: cannot read ansi-sym");
  1313.         }
  1314.         break;
  1315.     }
  1316. #endif
  1317. }
  1318.  
  1319.  
  1320. short
  1321. RTFGetCharSet ()
  1322. {
  1323.     return (curCharSet);
  1324. }
  1325.  
  1326.  
  1327. /* ---------------------------------------------------------------------- */
  1328.  
  1329. /*
  1330.  * Special destination readers.  They gobble the destination so the
  1331.  * writer doesn't have to deal with them.  That's wrong for any
  1332.  * translator that wants to process any of these itself.  In that
  1333.  * case, these readers should be overridden by installing a different
  1334.  * destination callback.
  1335.  *
  1336.  * NOTE: The last token read by each of these reader will be the
  1337.  * destination's terminating '}', which will then be the current token.
  1338.  * That '}' token is passed to RTFRouteToken() - the writer has already
  1339.  * seen the '{' that began the destination group, and may have pushed a
  1340.  * state; it also needs to know at the end of the group that a state
  1341.  * should be popped.
  1342.  *
  1343.  * It's important that rtf.h and the control token lookup table list
  1344.  * as many symbols as possible, because these destination readers
  1345.  * unfortunately make strict assumptions about the input they expect,
  1346.  * and a token of class rtfUnknown will throw them off easily.
  1347.  */
  1348.  
  1349.  
  1350. /*
  1351.  * Read { \fonttbl ... } destination.  Old font tables don't have
  1352.  * braces around each table entry; try to adjust for that.
  1353.  */
  1354.  
  1355. static void
  1356. ReadFontTbl ()
  1357. {
  1358. RTFFont    *fp;
  1359. char    buf[rtfBufSiz], *bp;
  1360. short    old = -1;
  1361. char    *fn = "ReadFontTbl";
  1362.  
  1363.     for (;;)
  1364.     {
  1365.         (void) RTFGetToken ();
  1366.         if (RTFCheckCM (rtfGroup, rtfEndGroup))
  1367.             break;
  1368.         if (old < 0)        /* first entry - determine tbl type */
  1369.         {
  1370.             if (RTFCheckCMM (rtfControl, rtfCharAttr, rtfFontNum))
  1371.                 old = 1;    /* no brace */
  1372.             else if (RTFCheckCM (rtfGroup, rtfBeginGroup))
  1373.                 old = 0;    /* brace */
  1374.             else            /* can't tell! */
  1375.                 RTFPanic ("%s: Cannot determine format", fn);
  1376.         }
  1377.         if (old == 0)        /* need to find "{" here */
  1378.         {
  1379.             if (!RTFCheckCM (rtfGroup, rtfBeginGroup))
  1380.                 RTFPanic ("%s: missing \"{\"", fn);
  1381.             (void) RTFGetToken ();    /* yes, skip to next token */
  1382.         }
  1383.         if ((fp = New (RTFFont)) == NULL)
  1384.             RTFPanic ("%s: cannot allocate font entry", fn);
  1385.  
  1386.         fp->rtfNextFont = fontList;
  1387.         fontList = fp;
  1388.  
  1389.         fp->rtfFName =   NULL;
  1390.         fp->rtfFAltName =  NULL;
  1391.         fp->rtfFNum = -1;
  1392.         fp->rtfFFamily = 0;
  1393.         fp->rtfFCharSet = 0;
  1394.         fp->rtfFPitch = 0;
  1395.         fp->rtfFType = 0;
  1396.         fp->rtfFCodePage = 0;
  1397.  
  1398.         while (rtfClass != rtfEOF && !RTFCheckCM (rtfText, ';'))
  1399.         {
  1400.             if (rtfClass == rtfControl)
  1401.             {
  1402.                 switch (rtfMajor)
  1403.                 {
  1404.                 default:
  1405.                     rtfTextBuf[rtfTextLen] = '\0'; 
  1406.                     /* ignore token but announce it */
  1407.                     RTFMsg ("%s: unknown token \"%s\"\n",
  1408.                             fn, rtfTextBuf);
  1409.                 case rtfFontFamily:
  1410.                     fp->rtfFFamily = rtfMinor;
  1411.                     break;
  1412.                 case rtfCharAttr:
  1413.                     switch (rtfMinor)
  1414.                     {
  1415.                     default:
  1416.                         break;    /* ignore unknown? */
  1417.                     case rtfFontNum:
  1418.                         fp->rtfFNum = rtfParam;
  1419.                         break;
  1420.                     }
  1421.                     break;
  1422.                 case rtfFontAttr:
  1423.                     switch (rtfMinor)
  1424.                     {
  1425.                     default:
  1426.                         break;    /* ignore unknown? */
  1427.                     case rtfFontCharSet:
  1428.                         fp->rtfFCharSet = rtfParam;
  1429.                         break;
  1430.                     case rtfFontPitch:
  1431.                         fp->rtfFPitch = rtfParam;
  1432.                         break;
  1433.                     case rtfFontCodePage:
  1434.                         fp->rtfFCodePage = rtfParam;
  1435.                         break;
  1436.                     case rtfFTypeNil:
  1437.                     case rtfFTypeTrueType:
  1438.                         fp->rtfFType = rtfParam;
  1439.                         break;
  1440.                     }
  1441.                     break;
  1442.                 }
  1443.             }
  1444.             else if (RTFCheckCM (rtfGroup, rtfBeginGroup))    /* dest */
  1445.             {
  1446.                 RTFSkipGroup ();    /* ignore for now */
  1447.             }
  1448.             else if (rtfClass == rtfText)    /* font name */
  1449.             {
  1450.                 bp = buf;
  1451.                 while (rtfClass != rtfEOF
  1452.                     && !RTFCheckCM (rtfText, ';'))
  1453.                 {
  1454.                     *bp++ = rtfMajor;
  1455.                     (void) RTFGetToken ();
  1456.                 }
  1457.                 *bp = '\0';
  1458.                 fp->rtfFName = RTFStrSave (buf);
  1459.                 if (fp->rtfFName ==  NULL)
  1460.                     RTFPanic ("%s: cannot allocate font name", fn);
  1461.                 /* already have next token; don't read one */
  1462.                 /* at bottom of loop */
  1463.                 continue;
  1464.             }
  1465.             else
  1466.             {
  1467.                 rtfTextBuf[rtfTextLen] = '\0'; 
  1468.                 /* ignore token but announce it */
  1469.                 RTFMsg ("%s: unknown token \"%s\"\n",
  1470.                             fn, rtfTextBuf);
  1471.             }
  1472.             (void) RTFGetToken ();
  1473.         }
  1474.         if (old == 0)    /* need to see "}" here */
  1475.         {
  1476.             (void) RTFGetToken ();
  1477.             if (!RTFCheckCM (rtfGroup, rtfEndGroup))
  1478.                 RTFPanic ("%s: missing \"}\"", fn);
  1479.         }
  1480.     }
  1481.     if (fp->rtfFNum == -1)
  1482.         RTFPanic ("%s: missing font number", fn);
  1483. /*
  1484.  * Could check other pieces of structure here, too, I suppose.
  1485.  */
  1486.     RTFRouteToken ();    /* feed "}" back to router */
  1487. }
  1488.  
  1489.  
  1490. /*
  1491.  * The color table entries have color values of -1 if
  1492.  * the default color should be used for the entry (only
  1493.  * a semi-colon is given in the definition, no color values).
  1494.  * There will be a problem if a partial entry (1 or 2 but
  1495.  * not 3 color values) is given.  The possibility is ignored
  1496.  * here.
  1497.  */
  1498.  
  1499. static void
  1500. ReadColorTbl ()
  1501. {
  1502. RTFColor    *cp;
  1503. short        cnum = 0;
  1504. char        *fn = "ReadColorTbl";
  1505.  
  1506.     for (;;)
  1507.     {
  1508.         (void) RTFGetToken ();
  1509.         if (RTFCheckCM (rtfGroup, rtfEndGroup))
  1510.             break;
  1511.         if ((cp = New (RTFColor)) == NULL)
  1512.             RTFPanic ("%s: cannot allocate color entry", fn);
  1513.         cp->rtfCNum = cnum++;
  1514.         cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1;
  1515.         cp->rtfNextColor = colorList;
  1516.         colorList = cp;
  1517.         while (RTFCheckCM (rtfControl, rtfColorName))
  1518.         {
  1519.             switch (rtfMinor)
  1520.             {
  1521.             case rtfRed:    cp->rtfCRed = rtfParam; break;
  1522.             case rtfGreen:    cp->rtfCGreen = rtfParam; break;
  1523.             case rtfBlue:    cp->rtfCBlue = rtfParam; break;
  1524.             }
  1525.             RTFGetToken ();
  1526.         }
  1527.         if (!RTFCheckCM (rtfText, (short) ';'))
  1528.             RTFPanic ("%s: malformed entry", fn);
  1529.     }
  1530.     RTFRouteToken ();    /* feed "}" back to router */
  1531. }
  1532.  
  1533.  
  1534. /*
  1535.  * The "Normal" style definition doesn't contain any style number,
  1536.  * all others do.  Normal style is given style rtfNormalStyleNum.
  1537.  */
  1538.  
  1539. static void
  1540. ReadStyleSheet ()
  1541. {
  1542. RTFStyle    *sp;
  1543. RTFStyleElt    *sep, *sepLast;
  1544. char        buf[rtfBufSiz], *bp;
  1545. char        *fn = "ReadStyleSheet";
  1546. #ifdef DCLAP
  1547. short            lastWasFontnum;
  1548. #endif
  1549.  
  1550.     for (;;)
  1551.     {
  1552.         (void) RTFGetToken ();
  1553.         if (RTFCheckCM (rtfGroup, rtfEndGroup))
  1554.             break;
  1555.         if ((sp = New (RTFStyle)) ==  NULL)
  1556.             RTFPanic ("%s: cannot allocate stylesheet entry", fn);
  1557.         sp->rtfSName = NULL;
  1558.         sp->rtfSNum = -1;
  1559.         sp->rtfSType = rtfParStyle;
  1560.         sp->rtfSAdditive = 0;
  1561.         sp->rtfSBasedOn = rtfNoStyleNum;
  1562.         sp->rtfSNextPar = -1;
  1563.         sp->rtfSSEList = sepLast =  NULL;
  1564.         sp->rtfNextStyle = styleList;
  1565.         sp->rtfExpanding = 0;
  1566.         styleList = sp;
  1567.         if (!RTFCheckCM (rtfGroup, rtfBeginGroup))
  1568.             RTFPanic ("%s: missing \"{\"", fn);
  1569. #ifdef DCLAP
  1570.         lastWasFontnum = 0;
  1571. #endif
  1572.  
  1573.         for (;;)
  1574.         {
  1575.             (void) RTFGetToken ();
  1576.  
  1577. #ifdef DCLAP
  1578.     /* obscure problem w/ MSWord-Mac-v5 
  1579.     -- it doesn't write \fs24 in the stylesheet (fs24 = default size)
  1580.     -- look for any font spec \f# and append a \fs24 here (even if it is followed by fs?)
  1581.     */
  1582.                 if (lastWasFontnum) {
  1583.                  if (rtfMinor != rtfFontSize) {
  1584.                     if ((sep = New (RTFStyleElt)) ==  NULL)
  1585.                         RTFPanic ("%s: cannot allocate style element", fn);
  1586.                     sep->rtfSEClass = rtfControl;
  1587.                     sep->rtfSEMajor = rtfCharAttr;
  1588.                     sep->rtfSEMinor = rtfFontSize;
  1589.                     sep->rtfSEParam = 24;
  1590.                     if ((sep->rtfSEText = RTFStrSave ("24")) == NULL)
  1591.                         RTFPanic ("%s: cannot allocate style element text", fn);
  1592.                     sepLast->rtfNextSE = sep;
  1593.                     sep->rtfNextSE =  NULL;
  1594.                     sepLast = sep;
  1595.                     }
  1596.                     }
  1597.                 lastWasFontnum = RTFCheckMM( rtfCharAttr, rtfFontNum);
  1598.                 if (lastWasFontnum) {
  1599.                     /* break here for debug... */
  1600.                     lastWasFontnum = 1;
  1601.                     }
  1602. #endif
  1603.  
  1604.             if (rtfClass == rtfEOF
  1605.                 || RTFCheckCM (rtfText, ';'))
  1606.                 break;
  1607.             if (rtfClass == rtfControl)
  1608.             {
  1609.                 if (RTFCheckMM (rtfSpecialChar, rtfOptDest))
  1610.                     continue;    /* ignore "\*" */
  1611.                 if (RTFCheckMM (rtfParAttr, rtfStyleNum))
  1612.                 {
  1613.                     sp->rtfSNum = rtfParam;
  1614.                     sp->rtfSType = rtfParStyle;
  1615.                     continue;
  1616.                 }
  1617.                 if (RTFCheckMM (rtfCharAttr, rtfCharStyleNum))
  1618.                 {
  1619.                     sp->rtfSNum = rtfParam;
  1620.                     sp->rtfSType = rtfCharStyle;
  1621.                     continue;
  1622.                 }
  1623.                 if (RTFCheckMM (rtfSectAttr, rtfSectStyleNum))
  1624.                 {
  1625.                     sp->rtfSNum = rtfParam;
  1626.                     sp->rtfSType = rtfSectStyle;
  1627.                     continue;
  1628.                 }
  1629.                 if (RTFCheckMM (rtfStyleAttr, rtfBasedOn))
  1630.                 {
  1631.                     sp->rtfSBasedOn = rtfParam;
  1632.                     continue;
  1633.                 }
  1634.                 if (RTFCheckMM (rtfStyleAttr, rtfAdditive))
  1635.                 {
  1636.                     sp->rtfSAdditive = 1;
  1637.                     continue;
  1638.                 }
  1639.                 if (RTFCheckMM (rtfStyleAttr, rtfNext))
  1640.                 {
  1641.                     sp->rtfSNextPar = rtfParam;
  1642.                     continue;
  1643.                 }
  1644.                 
  1645.  
  1646.                 if ((sep = New (RTFStyleElt)) ==  NULL)
  1647.                     RTFPanic ("%s: cannot allocate style element", fn);
  1648.                 sep->rtfSEClass = rtfClass;
  1649.                 sep->rtfSEMajor = rtfMajor;
  1650.                 sep->rtfSEMinor = rtfMinor;
  1651.                 sep->rtfSEParam = rtfParam;
  1652.                 rtfTextBuf[rtfTextLen] = '\0'; 
  1653.                 if ((sep->rtfSEText = RTFStrSave (rtfTextBuf))
  1654.                                 == NULL)
  1655.                     RTFPanic ("%s: cannot allocate style element text", fn);
  1656.                 if (sepLast ==  NULL)
  1657.                     sp->rtfSSEList = sep;    /* first element */
  1658.                 else                /* add to end */
  1659.                     sepLast->rtfNextSE = sep;
  1660.                 sep->rtfNextSE = NULL;
  1661.                 sepLast = sep;
  1662.             }
  1663.             else if (RTFCheckCM (rtfGroup, rtfBeginGroup))
  1664.             {
  1665.                 /*
  1666.                  * This passes over "{\*\keycode ... }, among
  1667.                  * other things. A temporary (perhaps) hack.
  1668.                  */
  1669.                 RTFSkipGroup ();
  1670.                 continue;
  1671.             }
  1672.             else if (rtfClass == rtfText)    /* style name */
  1673.             {
  1674.                 bp = buf;
  1675.                 while (rtfClass == rtfText)
  1676.                 {
  1677.                     if (rtfMajor == ';')
  1678.                     {
  1679.                         /* put back for "for" loop */
  1680.                         (void) RTFUngetToken ();
  1681.                         break;
  1682.                     }
  1683.                     *bp++ = rtfMajor;
  1684.                     (void) RTFGetToken ();
  1685.                 }
  1686.                 *bp = '\0';
  1687.                 if ((sp->rtfSName = RTFStrSave (buf)) == NULL)
  1688.                     RTFPanic ("%s: cannot allocate style name", fn);
  1689.             }
  1690.             else        /* unrecognized */
  1691.             {
  1692.                 /* ignore token but announce it */
  1693.                 rtfTextBuf[rtfTextLen] = '\0'; 
  1694.                  RTFMsg ("%s: unknown token \"%s\"\n",
  1695.                             fn, rtfTextBuf);
  1696.             }
  1697.         }
  1698.         (void) RTFGetToken ();
  1699.         if (!RTFCheckCM (rtfGroup, rtfEndGroup))
  1700.             RTFPanic ("%s: missing \"}\"", fn);
  1701.  
  1702.         /*
  1703.          * Check over the style structure.  A name is a must.
  1704.          * If no style number was specified, check whether it's the
  1705.          * Normal style (in which case it's given style number
  1706.          * rtfNormalStyleNum).  Note that some "normal" style names
  1707.          * just begin with "Normal" and can have other stuff following,
  1708.          * e.g., "Normal,Times 10 point".  Ugh.
  1709.          *
  1710.          * Some German RTF writers use "Standard" instead of "Normal".
  1711.          */
  1712.         if (sp->rtfSName == NULL)
  1713.             RTFPanic ("%s: missing style name", fn);
  1714.         if (sp->rtfSNum < 0)
  1715.         {
  1716.             if (strncmp (buf, "Normal", 6) != 0
  1717.                 && strncmp (buf, "Standard", 8) != 0)
  1718.                 RTFPanic ("%s: missing style number", fn);
  1719.             sp->rtfSNum = rtfNormalStyleNum;
  1720.         }
  1721.         if (sp->rtfSNextPar == -1)    /* if \snext not given, */
  1722.             sp->rtfSNextPar = sp->rtfSNum;    /* next is itself */
  1723.     }
  1724.     RTFRouteToken ();    /* feed "}" back to router */
  1725. }
  1726.  
  1727.  
  1728. static void
  1729. ReadInfoGroup ()
  1730. {
  1731.     RTFSkipGroup ();
  1732.     RTFRouteToken ();    /* feed "}" back to router */
  1733. }
  1734.  
  1735.  
  1736. static void
  1737. ReadPictGroup ()
  1738. {
  1739.     RTFSkipGroup ();
  1740.     RTFRouteToken ();    /* feed "}" back to router */
  1741. }
  1742.  
  1743.  
  1744. static void
  1745. ReadObjGroup ()
  1746. {
  1747.     RTFSkipGroup ();
  1748.     RTFRouteToken ();    /* feed "}" back to router */
  1749. }
  1750.  
  1751.  
  1752. /* ---------------------------------------------------------------------- */
  1753.  
  1754. /*
  1755.  * Routines to return pieces of stylesheet, or font or color tables.
  1756.  * References to style 0 are mapped onto the Normal style.
  1757.  */
  1758.  
  1759.  
  1760. RTFStyle *
  1761. RTFGetStyle (short num)
  1762. {
  1763. RTFStyle    *s;
  1764.  
  1765.     if (num == -1)
  1766.         return (styleList);
  1767.     for (s = styleList; s !=  NULL; s = s->rtfNextStyle)
  1768.     {
  1769.         if (s->rtfSNum == num)
  1770.             break;
  1771.     }
  1772.     return (s);        /* NULL if not found */
  1773. }
  1774.  
  1775.  
  1776. RTFFont *
  1777. RTFGetFont (short num)
  1778. {
  1779. RTFFont    *f;
  1780.  
  1781.     if (num == -1)
  1782.         return (fontList);
  1783.     for (f = fontList; f != NULL; f = f->rtfNextFont)
  1784.     {
  1785.         if (f->rtfFNum == num)
  1786.             break;
  1787.     }
  1788.     return (f);        /* NULL if not found */
  1789. }
  1790.  
  1791.  
  1792. RTFColor *
  1793. RTFGetColor (short num)
  1794. {
  1795. RTFColor    *c;
  1796.  
  1797.     if (num == -1)
  1798.         return (colorList);
  1799.     for (c = colorList; c !=  NULL; c = c->rtfNextColor)
  1800.     {
  1801.         if (c->rtfCNum == num)
  1802.             break;
  1803.     }
  1804.     return (c);        /* NULL if not found */
  1805. }
  1806.  
  1807.  
  1808. /* ---------------------------------------------------------------------- */
  1809.  
  1810.  
  1811. /*
  1812.  * Expand style n, if there is such a style.
  1813.  */
  1814.  
  1815. void
  1816. RTFExpandStyle (short n)
  1817. {
  1818. RTFStyle    *s;
  1819. RTFStyleElt    *se;
  1820.  
  1821.     if (n == -1 || (s = RTFGetStyle (n)) ==  NULL)
  1822.         return;
  1823.     if (s->rtfExpanding != 0)
  1824.         RTFPanic ("Style expansion loop, style %d", n);
  1825.     s->rtfExpanding = 1;    /* set expansion flag for loop detection */
  1826.     /*
  1827.      * Expand "based-on" style (unless it's the same as the current
  1828.      * style -- Normal style usually gives itself as its own based-on
  1829.      * style).  Based-on style expansion is done by synthesizing
  1830.      * the token that the writer needs to see in order to trigger
  1831.      * another style expansion, and feeding to token back through
  1832.      * the router so the writer sees it.
  1833.      */
  1834.     if (n != s->rtfSBasedOn)
  1835.     {
  1836.         RTFSetToken (rtfControl, rtfParAttr, rtfStyleNum,
  1837.                             s->rtfSBasedOn, "\\s");
  1838.         RTFRouteToken ();
  1839.     }
  1840.     /*
  1841.      * Now route the tokens unique to this style.  RTFSetToken()
  1842.      * isn't used because it would add the param value to the end
  1843.      * of the token text, which already has it in.
  1844.      */
  1845.     for (se = s->rtfSSEList; se !=   NULL; se = se->rtfNextSE)
  1846.     {
  1847.         rtfClass = se->rtfSEClass;
  1848.         rtfMajor = se->rtfSEMajor;
  1849.         rtfMinor = se->rtfSEMinor;
  1850.         rtfParam = se->rtfSEParam;
  1851.         (void) strcpy (rtfTextBuf, se->rtfSEText);
  1852.         rtfTextLen = strlen (rtfTextBuf);
  1853.         RTFRouteToken ();
  1854.     }
  1855.     s->rtfExpanding = 0;    /* done - clear expansion flag */
  1856. }
  1857.  
  1858.  
  1859. /* ---------------------------------------------------------------------- */
  1860.  
  1861. /*
  1862.  * Control symbol lookup routines
  1863.  */
  1864.  
  1865.  
  1866. typedef struct RTFKey    RTFKey;
  1867.  
  1868. struct RTFKey
  1869. {
  1870.     short    rtfKMajor;    /* major number */
  1871.     short    rtfKMinor;    /* minor number */
  1872.     char    *rtfKStr;    /* symbol name */
  1873.     short    rtfKHash;    /* symbol name hash value */
  1874. };
  1875.  
  1876. /*
  1877.  * A minor number of -1 means the token has no minor number
  1878.  * (all valid minor numbers are >= 0).
  1879.  */
  1880.  
  1881. #ifdef COMP_SYMC
  1882. static RTFKey rtfKey[] =
  1883. #else
  1884. static FAR RTFKey    rtfKey[] =
  1885. #endif
  1886. {
  1887.     /*
  1888.      * Special characters
  1889.      */
  1890.  
  1891.     rtfSpecialChar,    rtfIIntVersion,        "vern",        0,
  1892.     rtfSpecialChar,    rtfICreateTime,        "creatim",    0,
  1893.     rtfSpecialChar,    rtfIRevisionTime,    "revtim",    0,
  1894.     rtfSpecialChar,    rtfIPrintTime,        "printim",    0,
  1895.     rtfSpecialChar,    rtfIBackupTime,        "buptim",    0,
  1896.     rtfSpecialChar,    rtfIEditTime,        "edmins",    0,
  1897.     rtfSpecialChar,    rtfIYear,        "yr",        0,
  1898.     rtfSpecialChar,    rtfIMonth,        "mo",        0,
  1899.     rtfSpecialChar,    rtfIDay,        "dy",        0,
  1900.     rtfSpecialChar,    rtfIHour,        "hr",        0,
  1901.     rtfSpecialChar,    rtfIMinute,        "min",        0,
  1902.     rtfSpecialChar,    rtfISecond,        "sec",        0,
  1903.     rtfSpecialChar,    rtfINPages,        "nofpages",    0,
  1904.     rtfSpecialChar,    rtfINWords,        "nofwords",    0,
  1905.     rtfSpecialChar,    rtfINChars,        "nofchars",    0,
  1906.     rtfSpecialChar,    rtfIIntID,        "id",        0,
  1907.  
  1908.     rtfSpecialChar,    rtfCurHeadDate,        "chdate",    0,
  1909.     rtfSpecialChar,    rtfCurHeadDateLong,    "chdpl",    0,
  1910.     rtfSpecialChar,    rtfCurHeadDateAbbrev,    "chdpa",    0,
  1911.     rtfSpecialChar,    rtfCurHeadTime,        "chtime",    0,
  1912.     rtfSpecialChar,    rtfCurHeadPage,        "chpgn",    0,
  1913.     rtfSpecialChar,    rtfSectNum,        "sectnum",    0,
  1914.     rtfSpecialChar,    rtfCurFNote,        "chftn",    0,
  1915.     rtfSpecialChar,    rtfCurAnnotRef,        "chatn",    0,
  1916.     rtfSpecialChar,    rtfFNoteSep,        "chftnsep",    0,
  1917.     rtfSpecialChar,    rtfFNoteCont,        "chftnsepc",    0,
  1918.     rtfSpecialChar,    rtfCell,        "cell",        0,
  1919.     rtfSpecialChar,    rtfRow,            "row",        0,
  1920.     rtfSpecialChar,    rtfPar,            "par",        0,
  1921.     /* newline and carriage return are synonyms for */
  1922.     /* \par when they are preceded by a \ character */
  1923.     rtfSpecialChar,    rtfPar,            "\n",        0,
  1924.     rtfSpecialChar,    rtfPar,            "\r",        0,
  1925.     rtfSpecialChar,    rtfSect,        "sect",        0,
  1926.     rtfSpecialChar,    rtfPage,        "page",        0,
  1927.     rtfSpecialChar,    rtfColumn,        "column",    0,
  1928.     rtfSpecialChar,    rtfLine,        "line",        0,
  1929.     rtfSpecialChar,    rtfSoftPage,        "softpage",    0,
  1930.     rtfSpecialChar,    rtfSoftColumn,        "softcol",    0,
  1931.     rtfSpecialChar,    rtfSoftLine,        "softline",    0,
  1932.     rtfSpecialChar,    rtfSoftLineHt,        "softlheight",    0,
  1933.     rtfSpecialChar,    rtfTab,            "tab",        0,
  1934.     rtfSpecialChar,    rtfEmDash,        "emdash",    0,
  1935.     rtfSpecialChar,    rtfEnDash,        "endash",    0,
  1936.     rtfSpecialChar,    rtfEmSpace,        "emspace",    0,
  1937.     rtfSpecialChar,    rtfEnSpace,        "enspace",    0,
  1938.     rtfSpecialChar,    rtfBullet,        "bullet",    0,
  1939.     rtfSpecialChar,    rtfLQuote,        "lquote",    0,
  1940.     rtfSpecialChar,    rtfRQuote,        "rquote",    0,
  1941.     rtfSpecialChar,    rtfLDblQuote,        "ldblquote",    0,
  1942.     rtfSpecialChar,    rtfRDblQuote,        "rdblquote",    0,
  1943.     rtfSpecialChar,    rtfFormula,        "|",        0,
  1944.     rtfSpecialChar,    rtfNoBrkSpace,        "~",        0,
  1945.     rtfSpecialChar,    rtfNoReqHyphen,        "-",        0,
  1946.     rtfSpecialChar,    rtfNoBrkHyphen,        "_",        0,
  1947.     rtfSpecialChar,    rtfOptDest,        "*",        0,
  1948.     rtfSpecialChar,    rtfLTRMark,        "ltrmark",    0,
  1949.     rtfSpecialChar,    rtfRTLMark,        "rtlmark",    0,
  1950.     rtfSpecialChar,    rtfNoWidthJoiner,    "zwj",        0,
  1951.     rtfSpecialChar,    rtfNoWidthNonJoiner,    "zwnj",        0,
  1952.     /* is this valid? */
  1953.     rtfSpecialChar,    rtfCurHeadPict,        "chpict",    0,
  1954.  
  1955.     /*
  1956.      * Character formatting attributes
  1957.      */
  1958.  
  1959.     rtfCharAttr,    rtfPlain,        "plain",    0,
  1960.     rtfCharAttr,    rtfBold,        "b",        0,
  1961.     rtfCharAttr,    rtfAllCaps,        "caps",        0,
  1962.     rtfCharAttr,    rtfDeleted,        "deleted",    0,
  1963.     rtfCharAttr,    rtfSubScript,        "dn",        0,
  1964.     rtfCharAttr,    rtfSubScrShrink,    "sub",        0,
  1965.     rtfCharAttr,    rtfNoSuperSub,        "nosupersub",    0,
  1966.     rtfCharAttr,    rtfExpand,        "expnd",    0,
  1967.     rtfCharAttr,    rtfExpandTwips,        "expndtw",    0,
  1968.     rtfCharAttr,    rtfKerning,        "kerning",    0,
  1969.     rtfCharAttr,    rtfFontNum,        "f",        0,
  1970.     rtfCharAttr,    rtfFontSize,        "fs",        0,
  1971.     rtfCharAttr,    rtfItalic,        "i",        0,
  1972.     rtfCharAttr,    rtfOutline,        "outl",        0,
  1973.     rtfCharAttr,    rtfRevised,        "revised",    0,
  1974.     rtfCharAttr,    rtfRevAuthor,        "revauth",    0,
  1975.     rtfCharAttr,    rtfRevDTTM,        "revdttm",    0,
  1976.     rtfCharAttr,    rtfSmallCaps,        "scaps",    0,
  1977.     rtfCharAttr,    rtfShadow,        "shad",        0,
  1978.     rtfCharAttr,    rtfStrikeThru,        "strike",    0,
  1979.     rtfCharAttr,    rtfUnderline,        "ul",        0,
  1980.     rtfCharAttr,    rtfDotUnderline,    "uld",        0,
  1981.     rtfCharAttr,    rtfDbUnderline,        "uldb",        0,
  1982.     rtfCharAttr,    rtfNoUnderline,        "ulnone",    0,
  1983.     rtfCharAttr,    rtfWordUnderline,    "ulw",        0,
  1984.     rtfCharAttr,    rtfSuperScript,        "up",        0,
  1985.     rtfCharAttr,    rtfSuperScrShrink,    "super",    0,
  1986.     rtfCharAttr,    rtfInvisible,        "v",        0,
  1987.     rtfCharAttr,    rtfForeColor,        "cf",        0,
  1988.     rtfCharAttr,    rtfBackColor,        "cb",        0,
  1989.     rtfCharAttr,    rtfRTLChar,        "rtlch",    0,
  1990.     rtfCharAttr,    rtfLTRChar,        "ltrch",    0,
  1991.     rtfCharAttr,    rtfCharStyleNum,    "cs",        0,
  1992.     rtfCharAttr,    rtfCharCharSet,        "cchs",        0,
  1993.     rtfCharAttr,    rtfLanguage,        "lang",        0,
  1994.     /* this has disappeared from spec 1.2 */
  1995.     rtfCharAttr,    rtfGray,        "gray",        0,
  1996.  
  1997.     /*
  1998.      * Paragraph formatting attributes
  1999.      */
  2000.  
  2001.     rtfParAttr,    rtfParDef,        "pard",        0,
  2002.     rtfParAttr,    rtfStyleNum,        "s",        0,
  2003.     rtfParAttr,    rtfHyphenate,        "hyphpar",    0,
  2004.     rtfParAttr,    rtfInTable,        "intbl",    0,
  2005.     rtfParAttr,    rtfKeep,        "keep",        0,
  2006.     rtfParAttr,    rtfNoWidowControl,    "nowidctlpar",    0,
  2007.     rtfParAttr,    rtfKeepNext,        "keepn",    0,
  2008.     rtfParAttr,    rtfOutlineLevel,    "level",    0,
  2009.     rtfParAttr,    rtfNoLineNum,        "noline",    0,
  2010.     rtfParAttr,    rtfPBBefore,        "pagebb",    0,
  2011.     rtfParAttr,    rtfSideBySide,        "sbys",        0,
  2012.     rtfParAttr,    rtfQuadLeft,        "ql",        0,
  2013.     rtfParAttr,    rtfQuadRight,        "qr",        0,
  2014.     rtfParAttr,    rtfQuadJust,        "qj",        0,
  2015.     rtfParAttr,    rtfQuadCenter,        "qc",        0,
  2016.     rtfParAttr,    rtfFirstIndent,        "fi",        0,
  2017.     rtfParAttr,    rtfLeftIndent,        "li",        0,
  2018.     rtfParAttr,    rtfRightIndent,        "ri",        0,
  2019.     rtfParAttr,    rtfSpaceBefore,        "sb",        0,
  2020.     rtfParAttr,    rtfSpaceAfter,        "sa",        0,
  2021.     rtfParAttr,    rtfSpaceBetween,    "sl",        0,
  2022.     rtfParAttr,    rtfSpaceMultiply,    "slmult",    0,
  2023.  
  2024.     rtfParAttr,    rtfSubDocument,        "subdocument",    0,
  2025.  
  2026.     rtfParAttr,    rtfRTLPar,        "rtlpar",    0,
  2027.     rtfParAttr,    rtfLTRPar,        "ltrpar",    0,
  2028.  
  2029.     rtfParAttr,    rtfTabPos,        "tx",        0,
  2030.     /*
  2031.      * FrameMaker writes \tql (to mean left-justified tab, apparently)
  2032.      * although it's not in the spec.  It's also redundant, since lj
  2033.      * tabs are the default.
  2034.      */
  2035.     rtfParAttr,    rtfTabLeft,        "tql",        0,
  2036.     rtfParAttr,    rtfTabRight,        "tqr",        0,
  2037.     rtfParAttr,    rtfTabCenter,        "tqc",        0,
  2038.     rtfParAttr,    rtfTabDecimal,        "tqdec",    0,
  2039.     rtfParAttr,    rtfTabBar,        "tb",        0,
  2040.     rtfParAttr,    rtfLeaderDot,        "tldot",    0,
  2041.     rtfParAttr,    rtfLeaderHyphen,    "tlhyph",    0,
  2042.     rtfParAttr,    rtfLeaderUnder,        "tlul",        0,
  2043.     rtfParAttr,    rtfLeaderThick,        "tlth",        0,
  2044.     rtfParAttr,    rtfLeaderEqual,        "tleq",        0,
  2045.  
  2046.     rtfParAttr,    rtfParLevel,        "pnlvl",    0,
  2047.     rtfParAttr,    rtfParBullet,        "pnlvlblt",    0,
  2048.     rtfParAttr,    rtfParSimple,        "pnlvlbody",    0,
  2049.     rtfParAttr,    rtfParNumCont,        "pnlvlcont",    0,
  2050.     rtfParAttr,    rtfParNumOnce,        "pnnumonce",    0,
  2051.     rtfParAttr,    rtfParNumAcross,    "pnacross",    0,
  2052.     rtfParAttr,    rtfParHangIndent,    "pnhang",    0,
  2053.     rtfParAttr,    rtfParNumRestart,    "pnrestart",    0,
  2054.     rtfParAttr,    rtfParNumCardinal,    "pncard",    0,
  2055.     rtfParAttr,    rtfParNumDecimal,    "pndec",    0,
  2056.     rtfParAttr,    rtfParNumULetter,    "pnucltr",    0,
  2057.     rtfParAttr,    rtfParNumURoman,    "pnucrm",    0,
  2058.     rtfParAttr,    rtfParNumLLetter,    "pnlcltr",    0,
  2059.     rtfParAttr,    rtfParNumLRoman,    "pnlcrm",    0,
  2060.     rtfParAttr,    rtfParNumOrdinal,    "pnord",    0,
  2061.     rtfParAttr,    rtfParNumOrdinalText,    "pnordt",    0,
  2062.     rtfParAttr,    rtfParNumBold,        "pnb",        0,
  2063.     rtfParAttr,    rtfParNumItalic,    "pni",        0,
  2064.     rtfParAttr,    rtfParNumAllCaps,    "pncaps",    0,
  2065.     rtfParAttr,    rtfParNumSmallCaps,    "pnscaps",    0,
  2066.     rtfParAttr,    rtfParNumUnder,        "pnul",        0,
  2067.     rtfParAttr,    rtfParNumDotUnder,    "pnuld",    0,
  2068.     rtfParAttr,    rtfParNumDbUnder,    "pnuldb",    0,
  2069.     rtfParAttr,    rtfParNumNoUnder,    "pnulnone",    0,
  2070.     rtfParAttr,    rtfParNumWordUnder,    "pnulw",    0,
  2071.     rtfParAttr,    rtfParNumStrikethru,    "pnstrike",    0,
  2072.     rtfParAttr,    rtfParNumForeColor,    "pncf",        0,
  2073.     rtfParAttr,    rtfParNumFont,        "pnf",        0,
  2074.     rtfParAttr,    rtfParNumFontSize,    "pnfs",        0,
  2075.     rtfParAttr,    rtfParNumIndent,    "pnindent",    0,
  2076.     rtfParAttr,    rtfParNumSpacing,    "pnsp",        0,
  2077.     rtfParAttr,    rtfParNumInclPrev,    "pnprev",    0,
  2078.     rtfParAttr,    rtfParNumCenter,    "pnqc",        0,
  2079.     rtfParAttr,    rtfParNumLeft,        "pnql",        0,
  2080.     rtfParAttr,    rtfParNumRight,        "pnqr",        0,
  2081.     rtfParAttr,    rtfParNumStartAt,    "pnstart",    0,
  2082.  
  2083.     rtfParAttr,    rtfBorderTop,        "brdrt",    0,
  2084.     rtfParAttr,    rtfBorderBottom,    "brdrb",    0,
  2085.     rtfParAttr,    rtfBorderLeft,        "brdrl",    0,
  2086.     rtfParAttr,    rtfBorderRight,        "brdrr",    0,
  2087.     rtfParAttr,    rtfBorderBetween,    "brdrbtw",    0,
  2088.     rtfParAttr,    rtfBorderBar,        "brdrbar",    0,
  2089.     rtfParAttr,    rtfBorderBox,        "box",        0,
  2090.     rtfParAttr,    rtfBorderSingle,    "brdrs",    0,
  2091.     rtfParAttr,    rtfBorderThick,        "brdrth",    0,
  2092.     rtfParAttr,    rtfBorderShadow,    "brdrsh",    0,
  2093.     rtfParAttr,    rtfBorderDouble,    "brdrdb",    0,
  2094.     rtfParAttr,    rtfBorderDot,        "brdrdot",    0,
  2095.     rtfParAttr,    rtfBorderDot,        "brdrdash",    0,
  2096.     rtfParAttr,    rtfBorderHair,        "brdrhair",    0,
  2097.     rtfParAttr,    rtfBorderWidth,        "brdrw",    0,
  2098.     rtfParAttr,    rtfBorderColor,        "brdrcf",    0,
  2099.     rtfParAttr,    rtfBorderSpace,        "brsp",        0,
  2100.  
  2101.     rtfParAttr,    rtfShading,        "shading",    0,
  2102.     rtfParAttr,    rtfBgPatH,        "bghoriz",    0,
  2103.     rtfParAttr,    rtfBgPatV,        "bgvert",    0,
  2104.     rtfParAttr,    rtfFwdDiagBgPat,    "bgfdiag",    0,
  2105.     rtfParAttr,    rtfBwdDiagBgPat,    "bgbdiag",    0,
  2106.     rtfParAttr,    rtfHatchBgPat,        "bgcross",    0,
  2107.     rtfParAttr,    rtfDiagHatchBgPat,    "bgdcross",    0,
  2108.     rtfParAttr,    rtfDarkBgPatH,        "bgdkhoriz",    0,
  2109.     rtfParAttr,    rtfDarkBgPatV,        "bgdkvert",    0,
  2110.     rtfParAttr,    rtfFwdDarkBgPat,    "bgdkfdiag",    0,
  2111.     rtfParAttr,    rtfBwdDarkBgPat,    "bgdkbdiag",    0,
  2112.     rtfParAttr,    rtfDarkHatchBgPat,    "bgdkcross",    0,
  2113.     rtfParAttr,    rtfDarkDiagHatchBgPat,    "bgdkdcross",    0,
  2114.     rtfParAttr,    rtfBgPatLineColor,    "cfpat",    0,
  2115.     rtfParAttr,    rtfBgPatColor,        "cbpat",    0,
  2116.  
  2117.     /*
  2118.      * Section formatting attributes
  2119.      */
  2120.  
  2121.     rtfSectAttr,    rtfSectDef,        "sectd",    0,
  2122.     rtfSectAttr,    rtfENoteHere,        "endnhere",    0,
  2123.     rtfSectAttr,    rtfPrtBinFirst,        "binfsxn",    0,
  2124.     rtfSectAttr,    rtfPrtBin,        "binsxn",    0,
  2125.     rtfSectAttr,    rtfSectStyleNum,    "ds",        0,
  2126.  
  2127.     rtfSectAttr,    rtfNoBreak,        "sbknone",    0,
  2128.     rtfSectAttr,    rtfColBreak,        "sbkcol",    0,
  2129.     rtfSectAttr,    rtfPageBreak,        "sbkpage",    0,
  2130.     rtfSectAttr,    rtfEvenBreak,        "sbkeven",    0,
  2131.     rtfSectAttr,    rtfOddBreak,        "sbkodd",    0,
  2132.  
  2133.     rtfSectAttr,    rtfColumns,        "cols",        0,
  2134.     rtfSectAttr,    rtfColumnSpace,        "colsx",    0,
  2135.     rtfSectAttr,    rtfColumnNumber,    "colno",    0,
  2136.     rtfSectAttr,    rtfColumnSpRight,    "colsr",    0,
  2137.     rtfSectAttr,    rtfColumnWidth,        "colw",        0,
  2138.     rtfSectAttr,    rtfColumnLine,        "linebetcol",    0,
  2139.  
  2140.     rtfSectAttr,    rtfLineModulus,        "linemod",    0,
  2141.     rtfSectAttr,    rtfLineDist,        "linex",    0,
  2142.     rtfSectAttr,    rtfLineStarts,        "linestarts",    0,
  2143.     rtfSectAttr,    rtfLineRestart,        "linerestart",    0,
  2144.     rtfSectAttr,    rtfLineRestartPg,    "lineppage",    0,
  2145.     rtfSectAttr,    rtfLineCont,        "linecont",    0,
  2146.  
  2147.     rtfSectAttr,    rtfSectPageWid,        "pgwsxn",    0,
  2148.     rtfSectAttr,    rtfSectPageHt,        "pghsxn",    0,
  2149.     rtfSectAttr,    rtfSectMarginLeft,    "marglsxn",    0,
  2150.     rtfSectAttr,    rtfSectMarginRight,    "margrsxn",    0,
  2151.     rtfSectAttr,    rtfSectMarginTop,    "margtsxn",    0,
  2152.     rtfSectAttr,    rtfSectMarginBottom,    "margbsxn",    0,
  2153.     rtfSectAttr,    rtfSectMarginGutter,    "guttersxn",    0,
  2154.     rtfSectAttr,    rtfSectLandscape,    "lndscpsxn",    0,
  2155.     rtfSectAttr,    rtfTitleSpecial,    "titlepg",    0,
  2156.     rtfSectAttr,    rtfHeaderY,        "headery",    0,
  2157.     rtfSectAttr,    rtfFooterY,        "footery",    0,
  2158.  
  2159.     rtfSectAttr,    rtfPageStarts,        "pgnstarts",    0,
  2160.     rtfSectAttr,    rtfPageCont,        "pgncont",    0,
  2161.     rtfSectAttr,    rtfPageRestart,        "pgnrestart",    0,
  2162.     rtfSectAttr,    rtfPageNumRight,    "pgnx",        0,
  2163.     rtfSectAttr,    rtfPageNumTop,        "pgny",        0,
  2164.     rtfSectAttr,    rtfPageDecimal,        "pgndec",    0,
  2165.     rtfSectAttr,    rtfPageURoman,        "pgnucrm",    0,
  2166.     rtfSectAttr,    rtfPageLRoman,        "pgnlcrm",    0,
  2167.     rtfSectAttr,    rtfPageULetter,        "pgnucltr",    0,
  2168.     rtfSectAttr,    rtfPageLLetter,        "pgnlcltr",    0,
  2169.     rtfSectAttr,    rtfPageNumHyphSep,    "pgnhnsh",    0,
  2170.     rtfSectAttr,    rtfPageNumSpaceSep,    "pgnhnsp",    0,
  2171.     rtfSectAttr,    rtfPageNumColonSep,    "pgnhnsc",    0,
  2172.     rtfSectAttr,    rtfPageNumEmdashSep,    "pgnhnsm",    0,
  2173.     rtfSectAttr,    rtfPageNumEndashSep,    "pgnhnsn",    0,
  2174.  
  2175.     rtfSectAttr,    rtfTopVAlign,        "vertalt",    0,
  2176.     /* misspelled as "vertal" in specification 1.0 */
  2177.     rtfSectAttr,    rtfBottomVAlign,    "vertalb",    0,
  2178.     rtfSectAttr,    rtfCenterVAlign,    "vertalc",    0,
  2179.     rtfSectAttr,    rtfJustVAlign,        "vertalj",    0,
  2180.  
  2181.     rtfSectAttr,    rtfRTLSect,        "rtlsect",    0,
  2182.     rtfSectAttr,    rtfLTRSect,        "ltrsect",    0,
  2183.  
  2184.     /* I've seen these in an old spec, but not in real files... */
  2185.     /*rtfSectAttr,    rtfNoBreak,        "nobreak",    0,*/
  2186.     /*rtfSectAttr,    rtfColBreak,        "colbreak",    0,*/
  2187.     /*rtfSectAttr,    rtfPageBreak,        "pagebreak",    0,*/
  2188.     /*rtfSectAttr,    rtfEvenBreak,        "evenbreak",    0,*/
  2189.     /*rtfSectAttr,    rtfOddBreak,        "oddbreak",    0,*/
  2190.  
  2191.     /*
  2192.      * Document formatting attributes
  2193.      */
  2194.  
  2195.     rtfDocAttr,    rtfDefTab,        "deftab",    0,
  2196.     rtfDocAttr,    rtfHyphHotZone,        "hyphhotz",    0,
  2197.     rtfDocAttr,    rtfHyphConsecLines,    "hyphconsec",    0,
  2198.     rtfDocAttr,    rtfHyphCaps,        "hyphcaps",    0,
  2199.     rtfDocAttr,    rtfHyphAuto,        "hyphauto",    0,
  2200.     rtfDocAttr,    rtfLineStart,        "linestart",    0,
  2201.     rtfDocAttr,    rtfFracWidth,        "fracwidth",    0,
  2202.     /* \makeback was given in old version of spec, it's now */
  2203.     /* listed as \makebackup */
  2204.     rtfDocAttr,    rtfMakeBackup,        "makeback",    0,
  2205.     rtfDocAttr,    rtfMakeBackup,        "makebackup",    0,
  2206.     rtfDocAttr,    rtfRTFDefault,        "defformat",    0,
  2207.     rtfDocAttr,    rtfPSOverlay,        "psover",    0,
  2208.     rtfDocAttr,    rtfDocTemplate,        "doctemp",    0,
  2209.     rtfDocAttr,    rtfDefLanguage,        "deflang",    0,
  2210.  
  2211.     rtfDocAttr,    rtfFENoteType,        "fet",        0,
  2212.     rtfDocAttr,    rtfFNoteEndSect,    "endnotes",    0,
  2213.     rtfDocAttr,    rtfFNoteEndDoc,        "enddoc",    0,
  2214.     rtfDocAttr,    rtfFNoteText,        "ftntj",    0,
  2215.     rtfDocAttr,    rtfFNoteBottom,        "ftnbj",    0,
  2216.     rtfDocAttr,    rtfENoteEndSect,    "aendnotes",    0,
  2217.     rtfDocAttr,    rtfENoteEndDoc,        "aenddoc",    0,
  2218.     rtfDocAttr,    rtfENoteText,        "aftntj",    0,
  2219.     rtfDocAttr,    rtfENoteBottom,        "aftnbj",    0,
  2220.     rtfDocAttr,    rtfFNoteStart,        "ftnstart",    0,
  2221.     rtfDocAttr,    rtfENoteStart,        "aftnstart",    0,
  2222.     rtfDocAttr,    rtfFNoteRestartPage,    "ftnrstpg",    0,
  2223.     rtfDocAttr,    rtfFNoteRestart,    "ftnrestart",    0,
  2224.     rtfDocAttr,    rtfFNoteRestartCont,    "ftnrstcont",    0,
  2225.     rtfDocAttr,    rtfENoteRestart,    "aftnrestart",    0,
  2226.     rtfDocAttr,    rtfENoteRestartCont,    "aftnrstcont",    0,
  2227.     rtfDocAttr,    rtfFNoteNumArabic,    "ftnnar",    0,
  2228.     rtfDocAttr,    rtfFNoteNumLLetter,    "ftnnalc",    0,
  2229.     rtfDocAttr,    rtfFNoteNumULetter,    "ftnnauc",    0,
  2230.     rtfDocAttr,    rtfFNoteNumLRoman,    "ftnnrlc",    0,
  2231.     rtfDocAttr,    rtfFNoteNumURoman,    "ftnnruc",    0,
  2232.     rtfDocAttr,    rtfFNoteNumChicago,    "ftnnchi",    0,
  2233.     rtfDocAttr,    rtfENoteNumArabic,    "aftnnar",    0,
  2234.     rtfDocAttr,    rtfENoteNumLLetter,    "aftnnalc",    0,
  2235.     rtfDocAttr,    rtfENoteNumULetter,    "aftnnauc",    0,
  2236.     rtfDocAttr,    rtfENoteNumLRoman,    "aftnnrlc",    0,
  2237.     rtfDocAttr,    rtfENoteNumURoman,    "aftnnruc",    0,
  2238.     rtfDocAttr,    rtfENoteNumChicago,    "aftnnchi",    0,
  2239.  
  2240.     rtfDocAttr,    rtfPaperWidth,        "paperw",    0,
  2241.     rtfDocAttr,    rtfPaperHeight,        "paperh",    0,
  2242.     rtfDocAttr,    rtfPaperSize,        "psz",        0,
  2243.     rtfDocAttr,    rtfLeftMargin,        "margl",    0,
  2244.     rtfDocAttr,    rtfRightMargin,        "margr",    0,
  2245.     rtfDocAttr,    rtfTopMargin,        "margt",    0,
  2246.     rtfDocAttr,    rtfBottomMargin,    "margb",    0,
  2247.     rtfDocAttr,    rtfFacingPage,        "facingp",    0,
  2248.     rtfDocAttr,    rtfGutterWid,        "gutter",    0,
  2249.     rtfDocAttr,    rtfMirrorMargin,    "margmirror",    0,
  2250.     rtfDocAttr,    rtfLandscape,        "landscape",    0,
  2251.     rtfDocAttr,    rtfPageStart,        "pgnstart",    0,
  2252.     rtfDocAttr,    rtfWidowCtrl,        "widowctrl",    0,
  2253.  
  2254.     rtfDocAttr,    rtfLinkStyles,        "linkstyles",    0,
  2255.  
  2256.     rtfDocAttr,    rtfNoAutoTabIndent,    "notabind",    0,
  2257.     rtfDocAttr,    rtfWrapSpaces,        "wraptrsp",    0,
  2258.     rtfDocAttr,    rtfPrintColorsBlack,    "prcolbl",    0,
  2259.     rtfDocAttr,    rtfNoExtraSpaceRL,    "noextrasprl",    0,
  2260.     rtfDocAttr,    rtfNoColumnBalance,    "nocolbal",    0,
  2261.     rtfDocAttr,    rtfCvtMailMergeQuote,    "cvmme",    0,
  2262.     rtfDocAttr,    rtfSuppressTopSpace,    "sprstsp",    0,
  2263.     rtfDocAttr,    rtfSuppressPreParSpace,    "sprsspbf",    0,
  2264.     rtfDocAttr,    rtfCombineTblBorders,    "otblrul",    0,
  2265.     rtfDocAttr,    rtfTranspMetafiles,    "transmf",    0,
  2266.     rtfDocAttr,    rtfSwapBorders,        "swpbdr",    0,
  2267.     rtfDocAttr,    rtfShowHardBreaks,    "brkfrm",    0,
  2268.  
  2269.     rtfDocAttr,    rtfFormProtected,    "formprot",    0,
  2270.     rtfDocAttr,    rtfAllProtected,    "allprot",    0,
  2271.     rtfDocAttr,    rtfFormShading,        "formshade",    0,
  2272.     rtfDocAttr,    rtfFormDisplay,        "formdisp",    0,
  2273.     rtfDocAttr,    rtfPrintData,        "printdata",    0,
  2274.  
  2275.     rtfDocAttr,    rtfRevProtected,    "revprot",    0,
  2276.     rtfDocAttr,    rtfRevisions,        "revisions",    0,
  2277.     rtfDocAttr,    rtfRevDisplay,        "revprop",    0,
  2278.     rtfDocAttr,    rtfRevBar,        "revbar",    0,
  2279.  
  2280.     rtfDocAttr,    rtfAnnotProtected,    "annotprot",    0,
  2281.  
  2282.     rtfDocAttr,    rtfRTLDoc,        "rtldoc",    0,
  2283.     rtfDocAttr,    rtfLTRDoc,        "ltrdoc",    0,
  2284.  
  2285.     /*
  2286.      * Style attributes
  2287.      */
  2288.  
  2289.     rtfStyleAttr,    rtfAdditive,        "additive",    0,
  2290.     rtfStyleAttr,    rtfBasedOn,        "sbasedon",    0,
  2291.     rtfStyleAttr,    rtfNext,        "snext",    0,
  2292.  
  2293.     /*
  2294.      * Picture attributes
  2295.      */
  2296.  
  2297.     rtfPictAttr,    rtfMacQD,        "macpict",    0,
  2298.     rtfPictAttr,    rtfPMMetafile,        "pmmetafile",    0,
  2299.     rtfPictAttr,    rtfWinMetafile,        "wmetafile",    0,
  2300.     rtfPictAttr,    rtfDevIndBitmap,    "dibitmap",    0,
  2301.     rtfPictAttr,    rtfWinBitmap,        "wbitmap",    0,
  2302.     rtfPictAttr,    rtfPixelBits,        "wbmbitspixel",    0,
  2303.     rtfPictAttr,    rtfBitmapPlanes,    "wbmplanes",    0,
  2304.     rtfPictAttr,    rtfBitmapWid,        "wbmwidthbytes", 0,
  2305.  
  2306.     rtfPictAttr,    rtfPicWid,        "picw",        0,
  2307.     rtfPictAttr,    rtfPicHt,        "pich",        0,
  2308.     rtfPictAttr,    rtfPicGoalWid,        "picwgoal",    0,
  2309.     rtfPictAttr,    rtfPicGoalHt,        "pichgoal",    0,
  2310.     /* these two aren't in the spec, but some writers emit them */
  2311.     rtfPictAttr,    rtfPicGoalWid,        "picwGoal",    0,
  2312.     rtfPictAttr,    rtfPicGoalHt,        "pichGoal",    0,
  2313.     rtfPictAttr,    rtfPicScaleX,        "picscalex",    0,
  2314.     rtfPictAttr,    rtfPicScaleY,        "picscaley",    0,
  2315.     rtfPictAttr,    rtfPicScaled,        "picscaled",    0,
  2316.     rtfPictAttr,    rtfPicCropTop,        "piccropt",    0,
  2317.     rtfPictAttr,    rtfPicCropBottom,    "piccropb",    0,
  2318.     rtfPictAttr,    rtfPicCropLeft,        "piccropl",    0,
  2319.     rtfPictAttr,    rtfPicCropRight,    "piccropr",    0,
  2320.  
  2321.     rtfPictAttr,    rtfPicMFHasBitmap,    "picbmp",    0,
  2322.     rtfPictAttr,    rtfPicMFBitsPerPixel,    "picbpp",    0,
  2323.  
  2324.     rtfPictAttr,    rtfPicBinary,        "bin",        0,
  2325.  
  2326.     /*
  2327.      * NeXT graphic attributes
  2328.      */
  2329.  
  2330.     rtfNeXTGrAttr,    rtfNeXTGWidth,        "width",    0,
  2331.     rtfNeXTGrAttr,    rtfNeXTGHeight,        "height",    0,
  2332.  
  2333.     /*
  2334.      * Destinations
  2335.      */
  2336.  
  2337.     rtfDestination,    rtfFontTbl,        "fonttbl",    0,
  2338.     rtfDestination,    rtfFontAltName,        "falt",        0,
  2339.     rtfDestination,    rtfEmbeddedFont,    "fonteb",    0,
  2340.     rtfDestination,    rtfFontFile,        "fontfile",    0,
  2341.     rtfDestination,    rtfFileTbl,        "filetbl",    0,
  2342.     rtfDestination,    rtfFileInfo,        "file",        0,
  2343.     rtfDestination,    rtfColorTbl,        "colortbl",    0,
  2344.     rtfDestination,    rtfStyleSheet,        "stylesheet",    0,
  2345.     rtfDestination,    rtfKeyCode,        "keycode",    0,
  2346.     rtfDestination,    rtfRevisionTbl,        "revtbl",    0,
  2347.     rtfDestination,    rtfInfo,        "info",        0,
  2348.     rtfDestination,    rtfITitle,        "title",    0,
  2349.     rtfDestination,    rtfISubject,        "subject",    0,
  2350.     rtfDestination,    rtfIAuthor,        "author",    0,
  2351.     rtfDestination,    rtfIOperator,        "operator",    0,
  2352.     rtfDestination,    rtfIKeywords,        "keywords",    0,
  2353.     rtfDestination,    rtfIComment,        "comment",    0,
  2354.     rtfDestination,    rtfIVersion,        "version",    0,
  2355.     rtfDestination,    rtfIDoccomm,        "doccomm",    0,
  2356.     /* \verscomm may not exist -- was seen in earlier spec version */
  2357.     rtfDestination,    rtfIVerscomm,        "verscomm",    0,
  2358.     rtfDestination,    rtfNextFile,        "nextfile",    0,
  2359.     rtfDestination,    rtfTemplate,        "template",    0,
  2360.     rtfDestination,    rtfFNSep,        "ftnsep",    0,
  2361.     rtfDestination,    rtfFNContSep,        "ftnsepc",    0,
  2362.     rtfDestination,    rtfFNContNotice,    "ftncn",    0,
  2363.     rtfDestination,    rtfENSep,        "aftnsep",    0,
  2364.     rtfDestination,    rtfENContSep,        "aftnsepc",    0,
  2365.     rtfDestination,    rtfENContNotice,    "aftncn",    0,
  2366.     rtfDestination,    rtfPageNumLevel,    "pgnhn",    0,
  2367.     rtfDestination,    rtfParNumLevelStyle,    "pnseclvl",    0,
  2368.     rtfDestination,    rtfHeader,        "header",    0,
  2369.     rtfDestination,    rtfFooter,        "footer",    0,
  2370.     rtfDestination,    rtfHeaderLeft,        "headerl",    0,
  2371.     rtfDestination,    rtfHeaderRight,        "headerr",    0,
  2372.     rtfDestination,    rtfHeaderFirst,        "headerf",    0,
  2373.     rtfDestination,    rtfFooterLeft,        "footerl",    0,
  2374.     rtfDestination,    rtfFooterRight,        "footerr",    0,
  2375.     rtfDestination,    rtfFooterFirst,        "footerf",    0,
  2376.     rtfDestination,    rtfParNumText,        "pntext",    0,
  2377.     rtfDestination,    rtfParNumbering,    "pn",        0,
  2378.     rtfDestination,    rtfParNumTextAfter,    "pntexta",    0,
  2379.     rtfDestination,    rtfParNumTextBefore,    "pntextb",    0,
  2380.     rtfDestination,    rtfBookmarkStart,    "bkmkstart",    0,
  2381.     rtfDestination,    rtfBookmarkEnd,        "bkmkend",    0,
  2382.     rtfDestination,    rtfPict,        "pict",        0,
  2383.     rtfDestination,    rtfObject,        "object",    0,
  2384.     rtfDestination,    rtfObjClass,        "objclass",    0,
  2385.     rtfDestination,    rtfObjName,        "objname",    0,
  2386.     rtfObjAttr,    rtfObjTime,        "objtime",    0,
  2387.     rtfDestination,    rtfObjData,        "objdata",    0,
  2388.     rtfDestination,    rtfObjAlias,        "objalias",    0,
  2389.     rtfDestination,    rtfObjSection,        "objsect",    0,
  2390.     /* objitem and objtopic aren't documented in the spec! */
  2391.     rtfDestination,    rtfObjItem,        "objitem",    0,
  2392.     rtfDestination,    rtfObjTopic,        "objtopic",    0,
  2393.     rtfDestination,    rtfObjResult,        "result",    0,
  2394.     rtfDestination,    rtfDrawObject,        "do",        0,
  2395.     rtfDestination,    rtfFootnote,        "footnote",    0,
  2396.     rtfDestination,    rtfAnnotRefStart,    "atrfstart",    0,
  2397.     rtfDestination,    rtfAnnotRefEnd,        "atrfend",    0,
  2398.     rtfDestination,    rtfAnnotID,        "atnid",    0,
  2399.     rtfDestination,    rtfAnnotAuthor,        "atnauthor",    0,
  2400.     rtfDestination,    rtfAnnotation,        "annotation",    0,
  2401.     rtfDestination,    rtfAnnotRef,        "atnref",    0,
  2402.     rtfDestination,    rtfAnnotTime,        "atntime",    0,
  2403.     rtfDestination,    rtfAnnotIcon,        "atnicn",    0,
  2404.     rtfDestination,    rtfField,        "field",    0,
  2405.     rtfDestination,    rtfFieldInst,        "fldinst",    0,
  2406.     rtfDestination,    rtfFieldResult,        "fldrslt",    0,
  2407.     rtfDestination,    rtfDataField,        "datafield",    0,
  2408.     rtfDestination,    rtfIndex,        "xe",        0,
  2409.     rtfDestination,    rtfIndexText,        "txe",        0,
  2410.     rtfDestination,    rtfIndexRange,        "rxe",        0,
  2411.     rtfDestination,    rtfTOC,            "tc",        0,
  2412.     rtfDestination,    rtfNeXTGraphic,        "NeXTGraphic",    0,
  2413.  
  2414.     /*
  2415.      * Font families
  2416.      */
  2417.  
  2418.     rtfFontFamily,    rtfFFNil,        "fnil",        0,
  2419.     rtfFontFamily,    rtfFFRoman,        "froman",    0,
  2420.     rtfFontFamily,    rtfFFSwiss,        "fswiss",    0,
  2421.     rtfFontFamily,    rtfFFModern,        "fmodern",    0,
  2422.     rtfFontFamily,    rtfFFScript,        "fscript",    0,
  2423.     rtfFontFamily,    rtfFFDecor,        "fdecor",    0,
  2424.     rtfFontFamily,    rtfFFTech,        "ftech",    0,
  2425.     rtfFontFamily,    rtfFFBidirectional,    "fbidi",    0,
  2426.  
  2427.     /*
  2428.      * Font attributes
  2429.      */
  2430.  
  2431.     rtfFontAttr,    rtfFontCharSet,        "fcharset",    0,
  2432.     rtfFontAttr,    rtfFontPitch,        "fprq",        0,
  2433.     rtfFontAttr,    rtfFontCodePage,    "cpg",        0,
  2434.     rtfFontAttr,    rtfFTypeNil,        "ftnil",    0,
  2435.     rtfFontAttr,    rtfFTypeTrueType,    "fttruetype",    0,
  2436.  
  2437.     /*
  2438.      * File table attributes
  2439.      */
  2440.  
  2441.     rtfFileAttr,    rtfFileNum,        "fid",        0,
  2442.     rtfFileAttr,    rtfFileRelPath,        "frelative",    0,
  2443.     rtfFileAttr,    rtfFileOSNum,        "fosnum",    0,
  2444.  
  2445.     /*
  2446.      * File sources
  2447.      */
  2448.  
  2449.     rtfFileSource,    rtfSrcMacintosh,    "fvalidmac",    0,
  2450.     rtfFileSource,    rtfSrcDOS,        "fvaliddos",    0,
  2451.     rtfFileSource,    rtfSrcNTFS,        "fvalidntfs",    0,
  2452.     rtfFileSource,    rtfSrcHPFS,        "fvalidhpfs",    0,
  2453.     rtfFileSource,    rtfSrcNetwork,        "fnetwork",    0,
  2454.  
  2455.     /*
  2456.      * Color names
  2457.      */
  2458.  
  2459.     rtfColorName,    rtfRed,            "red",        0,
  2460.     rtfColorName,    rtfGreen,        "green",    0,
  2461.     rtfColorName,    rtfBlue,        "blue",        0,
  2462.  
  2463.     /*
  2464.      * Charset names
  2465.      */
  2466.  
  2467.     rtfCharSet,    rtfMacCharSet,        "mac",        0,
  2468.     rtfCharSet,    rtfAnsiCharSet,        "ansi",        0,
  2469.     rtfCharSet,    rtfPcCharSet,        "pc",        0,
  2470.     rtfCharSet,    rtfPcaCharSet,        "pca",        0,
  2471.  
  2472.     /*
  2473.      * Table attributes
  2474.      */
  2475.  
  2476.     rtfTblAttr,    rtfRowDef,        "trowd",    0,
  2477.     rtfTblAttr,    rtfRowGapH,        "trgaph",    0,
  2478.     rtfTblAttr,    rtfCellPos,        "cellx",    0,
  2479.     rtfTblAttr,    rtfMergeRngFirst,    "clmgf",    0,
  2480.     rtfTblAttr,    rtfMergePrevious,    "clmrg",    0,
  2481.  
  2482.     rtfTblAttr,    rtfRowLeft,        "trql",        0,
  2483.     rtfTblAttr,    rtfRowRight,        "trqr",        0,
  2484.     rtfTblAttr,    rtfRowCenter,        "trqc",        0,
  2485.     rtfTblAttr,    rtfRowLeftEdge,        "trleft",    0,
  2486.     rtfTblAttr,    rtfRowHt,        "trrh",        0,
  2487.     rtfTblAttr,    rtfRowHeader,        "trhdr",    0,
  2488.     rtfTblAttr,    rtfRowKeep,        "trkeep",    0,
  2489.  
  2490.     rtfTblAttr,    rtfRTLRow,        "rtlrow",    0,
  2491.     rtfTblAttr,    rtfLTRRow,        "ltrrow",    0,
  2492.  
  2493.     rtfTblAttr,    rtfRowBordTop,        "trbrdrt",    0,
  2494.     rtfTblAttr,    rtfRowBordLeft,        "trbrdrl",    0,
  2495.     rtfTblAttr,    rtfRowBordBottom,    "trbrdrb",    0,
  2496.     rtfTblAttr,    rtfRowBordRight,    "trbrdrr",    0,
  2497.     rtfTblAttr,    rtfRowBordHoriz,    "trbrdrh",    0,
  2498.     rtfTblAttr,    rtfRowBordVert,        "trbrdrv",    0,
  2499.  
  2500.     rtfTblAttr,    rtfCellBordBottom,    "clbrdrb",    0,
  2501.     rtfTblAttr,    rtfCellBordTop,        "clbrdrt",    0,
  2502.     rtfTblAttr,    rtfCellBordLeft,    "clbrdrl",    0,
  2503.     rtfTblAttr,    rtfCellBordRight,    "clbrdrr",    0,
  2504.  
  2505.     rtfTblAttr,    rtfCellShading,        "clshdng",    0,
  2506.     rtfTblAttr,    rtfCellBgPatH,        "clbghoriz",    0,
  2507.     rtfTblAttr,    rtfCellBgPatV,        "clbgvert",    0,
  2508.     rtfTblAttr,    rtfCellFwdDiagBgPat,    "clbgfdiag",    0,
  2509.     rtfTblAttr,    rtfCellBwdDiagBgPat,    "clbgbdiag",    0,
  2510.     rtfTblAttr,    rtfCellHatchBgPat,    "clbgcross",    0,
  2511.     rtfTblAttr,    rtfCellDiagHatchBgPat,    "clbgdcross",    0,
  2512.     /*
  2513.      * The spec lists "clbgdkhor", but the corresponding non-cell
  2514.      * control is "bgdkhoriz".  At any rate Macintosh Word seems
  2515.      * to accept both "clbgdkhor" and "clbgdkhoriz".
  2516.      */
  2517.     rtfTblAttr,    rtfCellDarkBgPatH,    "clbgdkhoriz",    0,
  2518.     rtfTblAttr,    rtfCellDarkBgPatH,    "clbgdkhor",    0,
  2519.     rtfTblAttr,    rtfCellDarkBgPatV,    "clbgdkvert",    0,
  2520.     rtfTblAttr,    rtfCellFwdDarkBgPat,    "clbgdkfdiag",    0,
  2521.     rtfTblAttr,    rtfCellBwdDarkBgPat,    "clbgdkbdiag",    0,
  2522.     rtfTblAttr,    rtfCellDarkHatchBgPat,    "clbgdkcross",    0,
  2523.     rtfTblAttr,    rtfCellDarkDiagHatchBgPat, "clbgdkdcross",    0,
  2524.     rtfTblAttr,    rtfCellBgPatLineColor, "clcfpat",    0,
  2525.     rtfTblAttr,    rtfCellBgPatColor,    "clcbpat",    0,
  2526.  
  2527.     /*
  2528.      * Field attributes
  2529.      */
  2530.  
  2531.     rtfFieldAttr,    rtfFieldDirty,        "flddirty",    0,
  2532.     rtfFieldAttr,    rtfFieldEdited,        "fldedit",    0,
  2533.     rtfFieldAttr,    rtfFieldLocked,        "fldlock",    0,
  2534.     rtfFieldAttr,    rtfFieldPrivate,    "fldpriv",    0,
  2535.     rtfFieldAttr,    rtfFieldAlt,        "fldalt",    0,
  2536.  
  2537.     /*
  2538.      * Positioning attributes
  2539.      */
  2540.  
  2541.     rtfPosAttr,    rtfAbsWid,        "absw",        0,
  2542.     rtfPosAttr,    rtfAbsHt,        "absh",        0,
  2543.  
  2544.     rtfPosAttr,    rtfRPosMargH,        "phmrg",    0,
  2545.     rtfPosAttr,    rtfRPosPageH,        "phpg",        0,
  2546.     rtfPosAttr,    rtfRPosColH,        "phcol",    0,
  2547.     rtfPosAttr,    rtfPosX,        "posx",        0,
  2548.     rtfPosAttr,    rtfPosNegX,        "posnegx",    0,
  2549.     rtfPosAttr,    rtfPosXCenter,        "posxc",    0,
  2550.     rtfPosAttr,    rtfPosXInside,        "posxi",    0,
  2551.     rtfPosAttr,    rtfPosXOutSide,        "posxo",    0,
  2552.     rtfPosAttr,    rtfPosXRight,        "posxr",    0,
  2553.     rtfPosAttr,    rtfPosXLeft,        "posxl",    0,
  2554.  
  2555.     rtfPosAttr,    rtfRPosMargV,        "pvmrg",    0,
  2556.     rtfPosAttr,    rtfRPosPageV,        "pvpg",        0,
  2557.     rtfPosAttr,    rtfRPosParaV,        "pvpara",    0,
  2558.     rtfPosAttr,    rtfPosY,        "posy",        0,
  2559.     rtfPosAttr,    rtfPosNegY,        "posnegy",    0,
  2560.     rtfPosAttr,    rtfPosYInline,        "posyil",    0,
  2561.     rtfPosAttr,    rtfPosYTop,        "posyt",    0,
  2562.     rtfPosAttr,    rtfPosYCenter,        "posyc",    0,
  2563.     rtfPosAttr,    rtfPosYBottom,        "posyb",    0,
  2564.  
  2565.     rtfPosAttr,    rtfNoWrap,        "nowrap",    0,
  2566.     rtfPosAttr,    rtfDistFromTextAll,    "dxfrtext",    0,
  2567.     rtfPosAttr,    rtfDistFromTextX,    "dfrmtxtx",    0,
  2568.     rtfPosAttr,    rtfDistFromTextY,    "dfrmtxty",    0,
  2569.     /* \dyfrtext no longer exists in spec 1.2, apparently */
  2570.     /* replaced by \dfrmtextx and \dfrmtexty. */
  2571.     rtfPosAttr,    rtfTextDistY,        "dyfrtext",    0,
  2572.  
  2573.     rtfPosAttr,    rtfDropCapLines,    "dropcapli",    0,
  2574.     rtfPosAttr,    rtfDropCapType,        "dropcapt",    0,
  2575.  
  2576.     /*
  2577.      * Object controls
  2578.      */
  2579.  
  2580.     rtfObjAttr,    rtfObjEmb,        "objemb",    0,
  2581.     rtfObjAttr,    rtfObjLink,        "objlink",    0,
  2582.     rtfObjAttr,    rtfObjAutoLink,        "objautlink",    0,
  2583.     rtfObjAttr,    rtfObjSubscriber,    "objsub",    0,
  2584.     rtfObjAttr,    rtfObjPublisher,    "objpub",    0,
  2585.     rtfObjAttr,    rtfObjICEmb,        "objicemb",    0,
  2586.  
  2587.     rtfObjAttr,    rtfObjLinkSelf,        "linkself",    0,
  2588.     rtfObjAttr,    rtfObjLock,        "objupdate",    0,
  2589.     rtfObjAttr,    rtfObjUpdate,        "objlock",    0,
  2590.  
  2591.     rtfObjAttr,    rtfObjHt,        "objh",        0,
  2592.     rtfObjAttr,    rtfObjWid,        "objw",        0,
  2593.     rtfObjAttr,    rtfObjSetSize,        "objsetsize",    0,
  2594.     rtfObjAttr,    rtfObjAlign,        "objalign",    0,
  2595.     rtfObjAttr,    rtfObjTransposeY,    "objtransy",    0,
  2596.     rtfObjAttr,    rtfObjCropTop,        "objcropt",    0,
  2597.     rtfObjAttr,    rtfObjCropBottom,    "objcropb",    0,
  2598.     rtfObjAttr,    rtfObjCropLeft,        "objcropl",    0,
  2599.     rtfObjAttr,    rtfObjCropRight,    "objcropr",    0,
  2600.     rtfObjAttr,    rtfObjScaleX,        "objscalex",    0,
  2601.     rtfObjAttr,    rtfObjScaleY,        "objscaley",    0,
  2602.  
  2603.     rtfObjAttr,    rtfObjResRTF,        "rsltrtf",    0,
  2604.     rtfObjAttr,    rtfObjResPict,        "rsltpict",    0,
  2605.     rtfObjAttr,    rtfObjResBitmap,    "rsltbmp",    0,
  2606.     rtfObjAttr,    rtfObjResText,        "rslttxt",    0,
  2607.     rtfObjAttr,    rtfObjResMerge,        "rsltmerge",    0,
  2608.  
  2609.     rtfObjAttr,    rtfObjBookmarkPubObj,    "bkmkpub",    0,
  2610.     rtfObjAttr,    rtfObjPubAutoUpdate,    "pubauto",    0,
  2611.  
  2612.     /*
  2613.      * Associated character formatting attributes
  2614.      */
  2615.  
  2616.     rtfACharAttr,    rtfACBold,        "ab",        0,
  2617.     rtfACharAttr,    rtfACAllCaps,        "caps",        0,
  2618.     rtfACharAttr,    rtfACForeColor,        "acf",        0,
  2619.     rtfACharAttr,    rtfACSubScript,        "adn",        0,
  2620.     rtfACharAttr,    rtfACExpand,        "aexpnd",    0,
  2621.     rtfACharAttr,    rtfACFontNum,        "af",        0,
  2622.     rtfACharAttr,    rtfACFontSize,        "afs",        0,
  2623.     rtfACharAttr,    rtfACItalic,        "ai",        0,
  2624.     rtfACharAttr,    rtfACLanguage,        "alang",    0,
  2625.     rtfACharAttr,    rtfACOutline,        "aoutl",    0,
  2626.     rtfACharAttr,    rtfACSmallCaps,        "ascaps",    0,
  2627.     rtfACharAttr,    rtfACShadow,        "ashad",    0,
  2628.     rtfACharAttr,    rtfACStrikeThru,    "astrike",    0,
  2629.     rtfACharAttr,    rtfACUnderline,        "aul",        0,
  2630.     rtfACharAttr,    rtfACDotUnderline,    "auld",        0,
  2631.     rtfACharAttr,    rtfACDbUnderline,    "auldb",    0,
  2632.     rtfACharAttr,    rtfACNoUnderline,    "aulnone",    0,
  2633.     rtfACharAttr,    rtfACWordUnderline,    "aulw",        0,
  2634.     rtfACharAttr,    rtfACSuperScript,    "aup",        0,
  2635.  
  2636.     /*
  2637.      * Footnote attributes
  2638.      */
  2639.  
  2640.     rtfFNoteAttr,    rtfFNAlt,        "ftnalt",    0,
  2641.  
  2642.     /*
  2643.      * Key code attributes
  2644.      */
  2645.  
  2646.     rtfKeyCodeAttr,    rtfAltKey,        "alt",        0,
  2647.     rtfKeyCodeAttr,    rtfShiftKey,        "shift",    0,
  2648.     rtfKeyCodeAttr,    rtfControlKey,        "ctrl",        0,
  2649.     rtfKeyCodeAttr,    rtfFunctionKey,        "fn",        0,
  2650.  
  2651.     /*
  2652.      * Bookmark attributes
  2653.      */
  2654.  
  2655.     rtfBookmarkAttr, rtfBookmarkFirstCol,    "bkmkcolf",    0,
  2656.     rtfBookmarkAttr, rtfBookmarkLastCol,    "bkmkcoll",    0,
  2657.  
  2658.     /*
  2659.      * Index entry attributes
  2660.      */
  2661.  
  2662.     rtfIndexAttr,    rtfIndexNumber,        "xef",        0,
  2663.     rtfIndexAttr,    rtfIndexBold,        "bxe",        0,
  2664.     rtfIndexAttr,    rtfIndexItalic,        "ixe",        0,
  2665.  
  2666.     /*
  2667.      * Table of contents attributes
  2668.      */
  2669.  
  2670.     rtfTOCAttr,    rtfTOCType,        "tcf",        0,
  2671.     rtfTOCAttr,    rtfTOCLevel,        "tcl",        0,
  2672.  
  2673.     /*
  2674.      * Drawing object attributes
  2675.      */
  2676.  
  2677.     rtfDrawAttr,    rtfDrawLock,        "dolock",    0,
  2678.     rtfDrawAttr,    rtfDrawPageRelX,    "doxpage",    0,
  2679.     rtfDrawAttr,    rtfDrawColumnRelX,    "dobxcolumn",    0,
  2680.     rtfDrawAttr,    rtfDrawMarginRelX,    "dobxmargin",    0,
  2681.     rtfDrawAttr,    rtfDrawPageRelY,    "dobypage",    0,
  2682.     rtfDrawAttr,    rtfDrawColumnRelY,    "dobycolumn",    0,
  2683.     rtfDrawAttr,    rtfDrawMarginRelY,    "dobymargin",    0,
  2684.     rtfDrawAttr,    rtfDrawHeight,        "dobhgt",    0,
  2685.  
  2686.     rtfDrawAttr,    rtfDrawBeginGroup,    "dpgroup",    0,
  2687.     rtfDrawAttr,    rtfDrawGroupCount,    "dpcount",    0,
  2688.     rtfDrawAttr,    rtfDrawEndGroup,    "dpendgroup",    0,
  2689.     rtfDrawAttr,    rtfDrawArc,        "dparc",    0,
  2690.     rtfDrawAttr,    rtfDrawCallout,        "dpcallout",    0,
  2691.     rtfDrawAttr,    rtfDrawEllipse,        "dpellipse",    0,
  2692.     rtfDrawAttr,    rtfDrawLine,        "dpline",    0,
  2693.     rtfDrawAttr,    rtfDrawPolygon,        "dppolygon",    0,
  2694.     rtfDrawAttr,    rtfDrawPolyLine,    "dppolyline",    0,
  2695.     rtfDrawAttr,    rtfDrawRect,        "dprect",    0,
  2696.     rtfDrawAttr,    rtfDrawTextBox,        "dptxbx",    0,
  2697.  
  2698.     rtfDrawAttr,    rtfDrawOffsetX,        "dpx",        0,
  2699.     rtfDrawAttr,    rtfDrawSizeX,        "dpxsize",    0,
  2700.     rtfDrawAttr,    rtfDrawOffsetY,        "dpy",        0,
  2701.     rtfDrawAttr,    rtfDrawSizeY,        "dpysize",    0,
  2702.  
  2703.     rtfDrawAttr,    rtfCOAngle,        "dpcoa",    0,
  2704.     rtfDrawAttr,    rtfCOAccentBar,        "dpcoaccent",    0,
  2705.     rtfDrawAttr,    rtfCOBestFit,        "dpcobestfit",    0,
  2706.     rtfDrawAttr,    rtfCOBorder,        "dpcoborder",    0,
  2707.     rtfDrawAttr,    rtfCOAttachAbsDist,    "dpcodabs",    0,
  2708.     rtfDrawAttr,    rtfCOAttachBottom,    "dpcodbottom",    0,
  2709.     rtfDrawAttr,    rtfCOAttachCenter,    "dpcodcenter",    0,
  2710.     rtfDrawAttr,    rtfCOAttachTop,        "dpcodtop",    0,
  2711.     rtfDrawAttr,    rtfCOLength,        "dpcolength",    0,
  2712.     rtfDrawAttr,    rtfCONegXQuadrant,    "dpcominusx",    0,
  2713.     rtfDrawAttr,    rtfCONegYQuadrant,    "dpcominusy",    0,
  2714.     rtfDrawAttr,    rtfCOOffset,        "dpcooffset",    0,
  2715.     rtfDrawAttr,    rtfCOAttachSmart,    "dpcosmarta",    0,
  2716.     rtfDrawAttr,    rtfCODoubleLine,    "dpcotdouble",    0,
  2717.     rtfDrawAttr,    rtfCORightAngle,    "dpcotright",    0,
  2718.     rtfDrawAttr,    rtfCOSingleLine,    "dpcotsingle",    0,
  2719.     rtfDrawAttr,    rtfCOTripleLine,    "dpcottriple",    0,
  2720.  
  2721.     rtfDrawAttr,    rtfDrawTextBoxMargin,    "dptxbxmar",    0,
  2722.     rtfDrawAttr,    rtfDrawTextBoxText,    "dptxbxtext",    0,
  2723.     rtfDrawAttr,    rtfDrawRoundRect,    "dproundr",    0,
  2724.  
  2725.     rtfDrawAttr,    rtfDrawPointX,        "dpptx",    0,
  2726.     rtfDrawAttr,    rtfDrawPointY,        "dppty",    0,
  2727.     rtfDrawAttr,    rtfDrawPolyCount,    "dppolycount",    0,
  2728.  
  2729.     rtfDrawAttr,    rtfDrawArcFlipX,    "dparcflipx",    0,
  2730.     rtfDrawAttr,    rtfDrawArcFlipY,    "dparcflipy",    0,
  2731.  
  2732.     rtfDrawAttr,    rtfDrawLineBlue,    "dplinecob",    0,
  2733.     rtfDrawAttr,    rtfDrawLineGreen,    "dplinecog",    0,
  2734.     rtfDrawAttr,    rtfDrawLineRed,        "dplinecor",    0,
  2735.     rtfDrawAttr,    rtfDrawLinePalette,    "dplinepal",    0,
  2736.     rtfDrawAttr,    rtfDrawLineDashDot,    "dplinedado",    0,
  2737.     rtfDrawAttr,    rtfDrawLineDashDotDot,    "dplinedadodo",    0,
  2738.     rtfDrawAttr,    rtfDrawLineDash,    "dplinedash",    0,
  2739.     rtfDrawAttr,    rtfDrawLineDot,        "dplinedot",    0,
  2740.     rtfDrawAttr,    rtfDrawLineGray,    "dplinegray",    0,
  2741.     rtfDrawAttr,    rtfDrawLineHollow,    "dplinehollow",    0,
  2742.     rtfDrawAttr,    rtfDrawLineSolid,    "dplinesolid",    0,
  2743.     rtfDrawAttr,    rtfDrawLineWidth,    "dplinew",    0,
  2744.  
  2745.     rtfDrawAttr,    rtfDrawHollowEndArrow,    "dpaendhol",    0,
  2746.     rtfDrawAttr,    rtfDrawEndArrowLength,    "dpaendl",    0,
  2747.     rtfDrawAttr,    rtfDrawSolidEndArrow,    "dpaendsol",    0,
  2748.     rtfDrawAttr,    rtfDrawEndArrowWidth,    "dpaendw",    0,
  2749.     rtfDrawAttr,    rtfDrawHollowStartArrow,"dpastarthol",    0,
  2750.     rtfDrawAttr,    rtfDrawStartArrowLength,"dpastartl",    0,
  2751.     rtfDrawAttr,    rtfDrawSolidStartArrow,    "dpastartsol",    0,
  2752.     rtfDrawAttr,    rtfDrawStartArrowWidth,    "dpastartw",    0,
  2753.  
  2754.     rtfDrawAttr,    rtfDrawBgFillBlue,    "dpfillbgcb",    0,
  2755.     rtfDrawAttr,    rtfDrawBgFillGreen,    "dpfillbgcg",    0,
  2756.     rtfDrawAttr,    rtfDrawBgFillRed,    "dpfillbgcr",    0,
  2757.     rtfDrawAttr,    rtfDrawBgFillPalette,    "dpfillbgpal",    0,
  2758.     rtfDrawAttr,    rtfDrawBgFillGray,    "dpfillbggray",    0,
  2759.     rtfDrawAttr,    rtfDrawFgFillBlue,    "dpfillfgcb",    0,
  2760.     rtfDrawAttr,    rtfDrawFgFillGreen,    "dpfillfgcg",    0,
  2761.     rtfDrawAttr,    rtfDrawFgFillRed,    "dpfillfgcr",    0,
  2762.     rtfDrawAttr,    rtfDrawFgFillPalette,    "dpfillfgpal",    0,
  2763.     rtfDrawAttr,    rtfDrawFgFillGray,    "dpfillfggray",    0,
  2764.     rtfDrawAttr,    rtfDrawFillPatIndex,    "dpfillpat",    0,
  2765.  
  2766.     rtfDrawAttr,    rtfDrawShadow,        "dpshadow",    0,
  2767.     rtfDrawAttr,    rtfDrawShadowXOffset,    "dpshadx",    0,
  2768.     rtfDrawAttr,    rtfDrawShadowYOffset,    "dpshady",    0,
  2769.  
  2770.     rtfVersion,    -1,            "rtf",        0,
  2771.     rtfDefFont,    -1,            "deff",        0,
  2772.  
  2773.     0,        -1,            NULL,    0
  2774. };
  2775.  
  2776.  
  2777. /*
  2778.  * Initialize lookup table hash values.  Only need to do this once.
  2779.  */
  2780.  
  2781. static void
  2782. LookupInit ()
  2783. {
  2784. static short    inited = 0;
  2785. RTFKey    *rp;
  2786.  
  2787.     if (inited == 0)
  2788.     {
  2789.         for (rp = rtfKey; rp->rtfKStr != NULL; rp++)
  2790.             rp->rtfKHash = Hash (rp->rtfKStr);
  2791.         ++inited;
  2792.     }
  2793. }
  2794.  
  2795.  
  2796. /*
  2797.  * Determine major and minor number of control token.  If it's
  2798.  * not found, the class turns into rtfUnknown.
  2799.  */
  2800.  
  2801. static void
  2802. Lookup (char    *s)
  2803. {
  2804. RTFKey    *rp;
  2805. short    hash;
  2806.  
  2807.     ++s;            /* skip over the leading \ character */
  2808.     hash = Hash (s);
  2809.     for (rp = rtfKey; rp->rtfKStr != NULL; rp++)
  2810.     {
  2811.         if (hash == rp->rtfKHash && strcmp (s, rp->rtfKStr) == 0)
  2812.         {
  2813.             rtfClass = rtfControl;
  2814.             rtfMajor = rp->rtfKMajor;
  2815.             rtfMinor = rp->rtfKMinor;
  2816.             return;
  2817.         }
  2818.     }
  2819.     rtfClass = rtfUnknown;
  2820. }
  2821.  
  2822.  
  2823. /*
  2824.  * Compute hash value of symbol
  2825.  */
  2826.  
  2827. static short
  2828. Hash (char    * s)
  2829. {
  2830. char    c;
  2831. short    val = 0;
  2832.  
  2833.     while ((c = *s++) != '\0')
  2834.         val += (short) c;
  2835.     return (val);
  2836. }
  2837.  
  2838.  
  2839. /* ---------------------------------------------------------------------- */
  2840.  
  2841. /*
  2842.  * Memory allocation routines
  2843.  */
  2844.  
  2845.  
  2846. /*
  2847.  * Return pointer to block of size bytes, or NULL if there's
  2848.  * not enough memory available.
  2849.  *
  2850.  * This is called through RTFAlloc(), a define which coerces the
  2851.  * argument to short.  This avoids the persistent problem of allocation
  2852.  * failing under THINK C when a long is passed.
  2853.  */
  2854.  
  2855. char *
  2856. _RTFAlloc (short size)
  2857. {
  2858. #ifdef DCLAP
  2859.     return ((char *) Nlm_MemNew(size));
  2860. #else
  2861.     return ((char *) malloc (size));
  2862. #endif
  2863. }
  2864.  
  2865.  
  2866. /*
  2867.  * Saves a string on the heap and returns a pointer to it.
  2868.  */
  2869.  
  2870.  
  2871. char *
  2872. RTFStrSave (char    *s)
  2873. {
  2874. #ifdef DCLAP
  2875.     return  Nlm_StringSave(s);
  2876. #else
  2877. char    *p;
  2878.  
  2879.     if ((p = RTFAlloc ((short) (strlen (s) + 1))) == NULL)
  2880.         return ( NULL);
  2881.     return (strcpy (p, s));
  2882. #endif
  2883. }
  2884.  
  2885.  
  2886. void
  2887. RTFFree (char    *p)
  2888. {
  2889. #ifdef DCLAP
  2890.     (void) Nlm_MemFree(p);
  2891. #else
  2892.     if (p != NULL)
  2893.         free (p);
  2894. #endif
  2895. }
  2896.  
  2897.  
  2898. /* ---------------------------------------------------------------------- */
  2899.  
  2900.  
  2901. /*
  2902.  * Token comparison routines
  2903.  */
  2904.  
  2905. short
  2906. RTFCheckCM (short aclass, short major)
  2907. {
  2908.     return (rtfClass == aclass && rtfMajor == major);
  2909. }
  2910.  
  2911.  
  2912. short
  2913. RTFCheckCMM (short aclass, short major, short minor)
  2914. {
  2915.     return (rtfClass == aclass && rtfMajor == major && rtfMinor == minor);
  2916. }
  2917.  
  2918.  
  2919. short
  2920. RTFCheckMM (short major, short minor)
  2921. {
  2922.     return (rtfMajor == major && rtfMinor == minor);
  2923. }
  2924.  
  2925.  
  2926. /* ---------------------------------------------------------------------- */
  2927.  
  2928.  
  2929. short
  2930. RTFCharToHex (char c)
  2931. {
  2932.     if (isupper (c))
  2933.         c = tolower (c);
  2934.     if (isdigit (c))
  2935.         return (c - '0');    /* '0'..'9' */
  2936.     return (c - 'a' + 10);        /* 'a'..'f' */
  2937. }
  2938.  
  2939.  
  2940. short
  2941. RTFHexToChar (short i)
  2942. {
  2943.     if (i < 10)
  2944.         return (i + '0');
  2945.     return (i - 10 + 'a');
  2946. }
  2947.  
  2948.  
  2949.  
  2950.  
  2951. /* ---------------------------------------------------------------------- */
  2952.  
  2953.  
  2954. /*
  2955.  * RTFReadOutputMap() -- Read output translation map
  2956.  */
  2957.  
  2958.  
  2959. /*
  2960.  * Read in a file describing the relation between the standard character set
  2961.  * and an RTF translator's corresponding output sequences.  Each line consists
  2962.  * of a standard character name and the output sequence for that character.
  2963.  *
  2964.  * outMap is an array of strings into which the sequences should be placed.
  2965.  * It should be declared like this in the calling program:
  2966.  *
  2967.  *    char *outMap[rtfSC_MaxChar];
  2968.  *
  2969.  * reinit should be non-zero if outMap should be initialized before reading the
  2970.  * file, zero otherwise.  (This allows the map to be constructed by reading
  2971.  * several files.)  It's assumed that any existing strings in the map were
  2972.  * allocated by RTFStrSave().  The map is initialized BEFORE any attempt is
  2973.  * made to read the file.
  2974.  *
  2975.  * If the filename is an absolute pathname, look in the specified location
  2976.  * only.  Otherwise try to find the file in the current directory or the
  2977.  * library directory.
  2978.  */
  2979.  
  2980. short
  2981. RTFReadOutputMap (char    *file, char    * outMap[], short reinit)
  2982. {
  2983. #if 0
  2984. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  2985. FILE    *f;
  2986. char    buf[rtfBufSiz];
  2987. char    *name, *seq;
  2988. short    stdCode;
  2989. short    i;
  2990. TSScanner    scanner;
  2991. char        *scanEscape;
  2992. char        *fn = "RTFReadOutputMap";
  2993.  
  2994.  
  2995.  
  2996.     /* clobber current mapping */
  2997.  
  2998.     if (reinit)
  2999.     {
  3000.         for (i = 0; i < rtfSC_MaxChar; i++)
  3001.         {
  3002.             RTFFree (outMap[i]);
  3003.             outMap[i] =  NULL;
  3004.         }
  3005.     }
  3006.  
  3007.     if ((f = RTFOpenLibFile (file, "r")) == NULL)
  3008.         return (0);
  3009.  
  3010.     /*
  3011.      * Turn off scanner's backslash escape mechanism while reading
  3012.      * file.  Restore it later.
  3013.      */
  3014.     TSGetScanner (&scanner);
  3015.     scanEscape = scanner.scanEscape;
  3016.     scanner.scanEscape = "";
  3017.     TSSetScanner (&scanner);
  3018.  
  3019.     /* read file */
  3020.  
  3021.     while (fgets (buf, (short) sizeof (buf), f) != NULL)
  3022.     {
  3023.         if(buf[0] == '#')    /* skip comment lines */
  3024.             continue;
  3025.         TSScanInit (buf);
  3026.         if ((name = TSScan ()) == NULL)
  3027.             continue;    /* skip blank lines */
  3028.         if ((stdCode = RTFStdCharCode (name)) < 0)
  3029.         {
  3030.             RTFMsg ("%s: unknown character name: %s\n", fn, name);
  3031.             continue;
  3032.         }
  3033.         if ((seq = TSScan ()) == NULL)
  3034.         {
  3035.             RTFMsg ("%s: malformed output sequence line for character %s\n", fn, name);
  3036.             continue;
  3037.         }
  3038.  
  3039. #ifdef DCLAP
  3040. /* dgg ++ let us use same input & output maps, & read the 0xAB char codes back to real chars */
  3041.         if (isdigit(seq[0]) && seq[1] > ' ')    /* convert to ascii value */
  3042.         {
  3043.             char* p = seq;
  3044.             short   value;
  3045.             short   radix = 10;
  3046.             if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
  3047.                 radix = 16;
  3048.                 p += 2;
  3049.                 }
  3050.             value = 0;
  3051.             while (*p != '\0') 
  3052.                 value = value * radix + RTFCharToHex(*p++);
  3053.             if (value < charSetSize) {
  3054.                 sprintf(buf,"%c", (unsigned char)value);
  3055.                 seq= buf;
  3056.                 }
  3057.         }
  3058. #endif
  3059.         if ((seq = RTFStrSave (seq)) == NULL)
  3060.             RTFPanic ("%s: out of memory", fn);
  3061.         outMap[stdCode] = seq;
  3062.     }
  3063.     scanner.scanEscape = scanEscape;
  3064.     TSSetScanner (&scanner);
  3065.     fclose(f);
  3066. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  3067. #endif
  3068.     return (1);
  3069. }
  3070.  
  3071.  
  3072.  
  3073. /* ---------------------------------------------------------------------- */
  3074.  
  3075. /*
  3076.  * Open a library file.
  3077.  */
  3078.  
  3079.  
  3080. static FILE    *(*libFileOpen) (char* file, char* mode) = NULL;
  3081.  
  3082.  
  3083.  
  3084. void
  3085. RTFSetOpenLibFileProc (LibFileOpen proc)
  3086. {
  3087.     libFileOpen = proc;
  3088. }
  3089.  
  3090.  
  3091. FILE * RTFOpenLibFile (char    *file, char    * mode)
  3092. {
  3093.     if (libFileOpen == NULL)
  3094.         return ( NULL);
  3095.     return ((*libFileOpen) (file, mode));
  3096. }
  3097.  
  3098.  
  3099. /* ---------------------------------------------------------------------- */
  3100.  
  3101. /*
  3102.  * Print message.  Default is to send message to stderr
  3103.  * but this may be overridden with RTFSetMsgProc().
  3104.  *
  3105.  * Message should include linefeeds as necessary.  If the default
  3106.  * function is overridden, the overriding function may want to
  3107.  * map linefeeds to another line ending character or sequence if
  3108.  * the host system doesn't use linefeeds.
  3109.  */
  3110.  
  3111.  
  3112. static void DefaultMsgProc (char    * s)
  3113. {
  3114. #ifdef DCLAP
  3115.     (void) Nlm_Message(MSG_OK, "%s", s);
  3116. #else
  3117.     fprintf (stderr, "%s", s);
  3118. #endif
  3119. }
  3120.  
  3121.  
  3122. static RTFFuncCharPtr    msgProc = DefaultMsgProc;
  3123.  
  3124.  
  3125. void
  3126. RTFSetMsgProc (RTFFuncCharPtr proc)
  3127. {
  3128.     msgProc = proc;
  3129. }
  3130.  
  3131.  
  3132. # ifdef STDARG
  3133.  
  3134. /*
  3135.  * This version is for systems with stdarg
  3136.  */
  3137.  
  3138. void
  3139. RTFMsg (char *fmt, ...)
  3140. {
  3141. char    buf[rtfBufSiz];
  3142.  
  3143.     va_list args;
  3144.     va_start (args,fmt);
  3145.     vsprintf (buf, fmt, args);
  3146.     va_end (args);
  3147.     (*msgProc) (buf);
  3148. }
  3149.  
  3150. # else /* !STDARG */
  3151.  
  3152. # ifdef    VARARGS
  3153.  
  3154.  
  3155. /*
  3156.  * This version is for systems that have varargs.
  3157.  */
  3158.  
  3159. void
  3160. RTFMsg (va_alist)
  3161. va_dcl
  3162. {
  3163. va_list    args;
  3164. char    *fmt;
  3165. char    buf[rtfBufSiz];
  3166.  
  3167.     va_start (args);
  3168.     fmt = va_arg (args, char *);
  3169.     vsprintf (buf, fmt, args);
  3170.     va_end (args);
  3171.     (*msgProc) (buf);
  3172. }
  3173.  
  3174. # else    /* !VARARGS */
  3175.  
  3176. /*
  3177.  * This version is for systems that don't have varargs.
  3178.  */
  3179.  
  3180. void
  3181. RTFMsg (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  3182. char    *fmt;
  3183. char    *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9;
  3184. {
  3185. char    buf[rtfBufSiz];
  3186.  
  3187.     sprintf (buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  3188.     (*msgProc) (buf);
  3189. }
  3190.  
  3191. # endif    /* !VARARGS */
  3192. # endif /* !STDARG */
  3193.  
  3194.  
  3195. /* ---------------------------------------------------------------------- */
  3196.  
  3197.  
  3198. /*
  3199.  * Process termination.  Print error message and exit.  Also prints
  3200.  * current token, and current input line number and position within
  3201.  * line if any input has been read from the current file.  (No input
  3202.  * has been read if prevChar is EOF).
  3203.  */
  3204.  
  3205. static void DefaultPanicProc (char    *s)
  3206. {
  3207. #ifdef DCLAP
  3208.     /* ?? give use a choice of dying or not w/ MSG_YESNO ?? */
  3209.     /* (void) Nlm_Message(MSG_FATAL, "%s", s); */
  3210.     (void) Nlm_Message( MSG_OK, "%s", s); 
  3211.     /* gReaderIsDead= 1; */
  3212. #else
  3213.     fprintf (stderr, "%s", s);
  3214.     exit (1);
  3215. #endif
  3216. }
  3217.  
  3218.  
  3219. static RTFFuncCharPtr    panicProc = DefaultPanicProc;
  3220.  
  3221.  
  3222. void
  3223. RTFSetPanicProc (RTFFuncCharPtr proc)
  3224. {
  3225.     panicProc = proc;
  3226. }
  3227.  
  3228.  
  3229. # ifdef STDARG
  3230.  
  3231. /*
  3232.  * This version is for systems with stdarg
  3233.  */
  3234.  
  3235. void
  3236. RTFPanic (char *fmt, ...)
  3237. {
  3238. char    buf[rtfBufSiz];
  3239.  
  3240.     va_list args;
  3241.     va_start (args,fmt);
  3242.     vsprintf (buf, fmt, args);
  3243.     va_end (args);
  3244.     (void) strcat (buf, "\n");
  3245.     if (prevChar != EOF && rtfTextBuf !=  NULL)
  3246.     {
  3247.         rtfTextBuf[rtfTextLen] = '\0'; 
  3248.         sprintf (buf + strlen (buf),
  3249.             "Last token read was \"%s\" near line %ld, position %d.\n",
  3250.             rtfTextBuf, rtfLineNum, rtfLinePos);
  3251.     }
  3252.     (*panicProc) (buf);
  3253. }
  3254.  
  3255. # else /* !STDARG */
  3256.  
  3257. # ifdef    VARARGS
  3258.  
  3259.  
  3260. /*
  3261.  * This version is for systems that have varargs.
  3262.  */
  3263.  
  3264. void
  3265. RTFPanic (va_alist)
  3266. va_dcl
  3267. {
  3268. va_list    args;
  3269. char    *fmt;
  3270. char    buf[rtfBufSiz];
  3271.  
  3272.     va_start (args);
  3273.     fmt = va_arg (args, char *);
  3274.     vsprintf (buf, fmt, args);
  3275.     va_end (args);
  3276.     (void) strcat (buf, "\n");
  3277.     if (prevChar != EOF && rtfTextBuf !=  NULL)
  3278.     {
  3279.         rtfTextBuf[rtfTextLen] = '\0'; 
  3280.         sprintf (buf + strlen (buf),
  3281.             "Last token read was \"%s\" near line %ld, position %d.\n",
  3282.             rtfTextBuf, rtfLineNum, rtfLinePos);
  3283.     }
  3284.     (*panicProc) (buf);
  3285. }
  3286.  
  3287. # else    /* !VARARGS */
  3288.  
  3289. /*
  3290.  * This version is for systems that don't have varargs.
  3291.  */
  3292.  
  3293. void
  3294. RTFPanic (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  3295. char    *fmt;
  3296. char    *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9;
  3297. {
  3298. char    buf[rtfBufSiz];
  3299.  
  3300.     sprintf (buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  3301.     (void) strcat (buf, "\n");
  3302.     if (prevChar != EOF && rtfTextBuf !=  NULL)
  3303.     {
  3304.         rtfTextBuf[rtfTextLen] = '\0'; 
  3305.         sprintf (buf + strlen (buf),
  3306.             "Last token read was \"%s\" near line %ld, position %d.\n",
  3307.             rtfTextBuf, rtfLineNum, rtfLinePos);
  3308.     }
  3309.     (*panicProc) (buf);
  3310. }
  3311.  
  3312. # endif    /* !VARARGS */
  3313. # endif /* !STDARG */
  3314.  
  3315.  
  3316.  
  3317.  
  3318.  
  3319.  
  3320.  
  3321. /* ------------------- TokenScan -------------------*/
  3322.  
  3323. typedef void (*VoidProc) (char    *p);
  3324. typedef char * (*CharPtrProc) (char    *p);
  3325.  
  3326.  
  3327. static short Search (char* s, char c);
  3328. static char    *CanonScan ();
  3329.  
  3330. static TSScanner    defScan =
  3331.     { NULL, CanonScan, " \t", "\"'", "\\", "\n\r", 0 };
  3332. static TSScanner    curScan =
  3333.     { NULL, CanonScan, " \t", "\"'", "\\", "\n\r", 0 };
  3334.  
  3335. static char    *curPos;
  3336. static short    emptyToken;
  3337.  
  3338.  
  3339. static void TSScanInit (char    *p)
  3340. {
  3341.     curPos = p;
  3342.     emptyToken = 0;
  3343.     if (curScan.scanInit != NULL)
  3344.         (*curScan.scanInit) (p);
  3345. }
  3346.  
  3347.  
  3348. static void TSSetScanner (TSScanner    *p)
  3349. {
  3350.     if (p == NULL || p->scanInit == NULL)
  3351.         curScan.scanInit = defScan.scanInit;
  3352.     else
  3353.         curScan.scanInit = p->scanInit;
  3354.     if (p == NULL || p->scanScan == NULL)
  3355.         curScan.scanScan = defScan.scanScan;
  3356.     else
  3357.         curScan.scanScan = p->scanScan;
  3358.  
  3359.     if (p == (TSScanner *) NULL || p->scanDelim == (char *) NULL)
  3360.         curScan.scanDelim = defScan.scanDelim;
  3361.     else
  3362.         curScan.scanDelim = p->scanDelim;
  3363.     if (p == (TSScanner *) NULL || p->scanQuote == (char *) NULL)
  3364.         curScan.scanQuote = defScan.scanQuote;
  3365.     else
  3366.         curScan.scanQuote = p->scanQuote;
  3367.     if (p == (TSScanner *) NULL || p->scanEscape == (char *) NULL)
  3368.         curScan.scanEscape = defScan.scanEscape;
  3369.     else
  3370.         curScan.scanEscape = p->scanEscape;
  3371.     if (p == (TSScanner *) NULL || p->scanEos == (char *) NULL)
  3372.         curScan.scanEos = defScan.scanEos;
  3373.     else
  3374.         curScan.scanEos = p->scanEos;
  3375.  
  3376.     if (p == (TSScanner *) NULL || p->scanFlags == 0)
  3377.         curScan.scanFlags = defScan.scanFlags;
  3378.     else
  3379.         curScan.scanFlags = p->scanFlags;
  3380. }
  3381.  
  3382.  
  3383. static void TSGetScanner (TSScanner    *p)
  3384. {
  3385.     p->scanInit = curScan.scanInit;
  3386.     p->scanScan = curScan.scanScan;
  3387.  
  3388.     p->scanDelim = curScan.scanDelim;
  3389.     p->scanQuote = curScan.scanQuote;
  3390.     p->scanEscape = curScan.scanEscape;
  3391.     p->scanEos = curScan.scanEos;
  3392.  
  3393.     p->scanFlags = curScan.scanFlags;
  3394. }
  3395.  
  3396.  
  3397. static void TSSetScanPos (char    *p)
  3398. {
  3399.     curPos = p;
  3400. }
  3401.  
  3402.  
  3403. static char * TSGetScanPos ()
  3404. {
  3405.     return (curPos);
  3406. }
  3407.  
  3408.  
  3409. /*
  3410.  * Search a (possibly NULL) string for a character.
  3411.  */
  3412.  
  3413. static short Search (char* s, char c)
  3414. {
  3415. char    c2;
  3416.  
  3417.     if (s != (char *) NULL)
  3418.     {
  3419.         while ((c2 = *s++) != '\0')
  3420.         {
  3421.             if (c == c2)
  3422.                 return (1);
  3423.         }
  3424.     }
  3425.     return (0);
  3426. }
  3427.  
  3428.  
  3429. static short TSIsScanDelim (char c)
  3430. {
  3431.     return (Search (curScan.scanDelim, c));
  3432. }
  3433.  
  3434.  
  3435. static short TSIsScanQuote (char c)
  3436. {
  3437.     return (Search (curScan.scanQuote, c));
  3438. }
  3439.  
  3440.  
  3441. static short TSIsScanEscape (char c)
  3442. {
  3443.     return (Search (curScan.scanEscape, c));
  3444. }
  3445.  
  3446.  
  3447. static short TSIsScanEos (char c)
  3448. {
  3449.     if (c == '\0')        /* null character ALWAYS terminates string */
  3450.         return (1);
  3451.     return (Search (curScan.scanEos, c));
  3452. }
  3453.  
  3454.  
  3455. static short TSTestScanFlags (short flags)
  3456. {
  3457.     return ((curScan.scanFlags & flags) == flags);
  3458. }
  3459.  
  3460.  
  3461. static char *
  3462. TSScan ()
  3463. {
  3464.     return ((*curScan.scanScan) ());
  3465. }
  3466.  
  3467.  
  3468. static char *
  3469. CanonScan ()
  3470. {
  3471. char    *pos, *start, *p, c, quote = 0;
  3472. short    escape = 0, haveToken = 0;
  3473.  
  3474.     if (emptyToken)        /* fix to point into buffer */
  3475.     {
  3476.         emptyToken = 0;
  3477.         return ("");
  3478.     }
  3479.     pos = TSGetScanPos ();
  3480.  
  3481.     if (!TSTestScanFlags (tsNoConcatDelims))
  3482.     {
  3483.         while (TSIsScanDelim (*pos))        /* skip delimiters */
  3484.             ++pos;
  3485.     }
  3486.     start = p = pos;            /* start of token */
  3487.     while (!TSIsScanEos (c = *pos))        /* eos terminates any token */
  3488.     {
  3489.         haveToken = 1;
  3490.         if (escape)            /* previous char was escape; */
  3491.         {                /* pass this one literally */
  3492.             *p++ = *pos++;
  3493.             escape = 0;
  3494.         }
  3495.         else if (TSIsScanEscape (c))    /* this char is escape; */
  3496.         {                /* pass next one literally */
  3497.             ++pos;
  3498.             escape = 1;
  3499.         }
  3500.         else if (quote)            /* in quote mode */
  3501.         {
  3502.             if (c == quote)        /* end quote mode */
  3503.                 quote = 0;
  3504.             else            /* no end quote yet */
  3505.                 *p++ = *pos;    /* add char */
  3506.             ++pos;            /* skip to next char */
  3507.         }
  3508.         else if (TSIsScanQuote (c))    /* begin quote mode */
  3509.         {
  3510.             ++pos;
  3511.             quote = c;
  3512.         }
  3513.         else if (TSIsScanDelim (c))    /* end of token */
  3514.         {
  3515.             ++pos;            /* skip past delimiter */
  3516.             /*
  3517.              * If also end of string and all delims are significant,
  3518.              * there's an implicit empty token at end.  We won't be
  3519.              * able to tell that from looking at the string itself,
  3520.              * so set a flag for next call.
  3521.              */
  3522.             if (TSIsScanEos (*pos)
  3523.                 && TSTestScanFlags (tsNoConcatDelims))
  3524.                 ++emptyToken;
  3525.             break;
  3526.         }
  3527.         else
  3528.             *p++ = *pos++;
  3529.     }
  3530.     *p = '\0';
  3531.     TSSetScanPos (pos);
  3532.     return (haveToken ? start : (char *) NULL);
  3533. }
  3534.  
  3535.